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


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2003-2006, GeoTools Project Managment Committee (PMC)
005:         *    (C) 2001, Institut de Recherche pour le Développement
006:         *    (C) 1998, Pêches et Océans Canada
007:         *  
008:         *    This library is free software; you can redistribute it and/or
009:         *    modify it under the terms of the GNU Lesser General Public
010:         *    License as published by the Free Software Foundation;
011:         *    version 2.1 of the License.
012:         *
013:         *    This library is distributed in the hope that it will be useful,
014:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
015:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
016:         *    Lesser General Public License for more details.
017:         */
018:        package org.geotools.measure;
019:
020:        // J2SE dependencies
021:        import java.text.DateFormat;
022:        import java.text.DecimalFormat;
023:        import java.text.FieldPosition;
024:        import java.text.Format;
025:        import java.text.NumberFormat;
026:        import java.text.ParsePosition;
027:        import java.text.SimpleDateFormat;
028:        import java.util.Date;
029:        import java.util.Locale;
030:        import java.util.TimeZone;
031:
032:        // Units dependencies
033:        import javax.units.Converter;
034:        import javax.units.NonSI;
035:        import javax.units.SI;
036:        import javax.units.Unit;
037:        import javax.units.UnitFormat;
038:
039:        // OpenGIS dependencies
040:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
041:        import org.opengis.referencing.cs.AxisDirection;
042:        import org.opengis.referencing.cs.CoordinateSystem;
043:        import org.opengis.referencing.cs.CoordinateSystemAxis;
044:        import org.opengis.referencing.datum.Datum;
045:        import org.opengis.referencing.datum.TemporalDatum;
046:        import org.opengis.geometry.DirectPosition;
047:        import org.opengis.geometry.MismatchedDimensionException;
048:
049:        // Geotools dependencies
050:        import org.geotools.referencing.CRS;
051:        import org.geotools.referencing.crs.DefaultTemporalCRS;
052:        import org.geotools.referencing.crs.DefaultGeographicCRS;
053:        import org.geotools.resources.CRSUtilities;
054:        import org.geotools.resources.i18n.ErrorKeys;
055:        import org.geotools.resources.i18n.Errors;
056:
057:        /**
058:         * Formats a {@linkplain org.geotools.geometry.GeneralDirectPosition direct position}
059:         * in an arbitrary {@linkplain CoordinateReferenceSystem coordinate reference system}.
060:         * The format for each ordinate is infered from the coordinate system units using the
061:         * following rules:
062:         * <ul>
063:         *   <li>Ordinate values in {@linkplain NonSI#DEGREE_ANGLE degrees} are formated as angles
064:         *       using {@link AngleFormat}.</li>
065:         *   <li>Ordinate values in any unit compatible with {@linkplain SI#SECOND seconds}
066:         *       are formated as dates using {@link DateFormat}.</li>
067:         *   <li>All other values are formatted as numbers using {@link NumberFormat}.</li>
068:         * </ul>
069:         *
070:         * <strong>Note:</strong> parsing is not yet implemented in this version.
071:         *
072:         * @since 2.0
073:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/measure/CoordinateFormat.java $
074:         * @version $Id: CoordinateFormat.java 24925 2007-03-27 20:12:08Z jgarnett $
075:         * @author Martin Desruisseaux
076:         */
077:        public class CoordinateFormat extends Format {
078:            /**
079:             * Serial number for interoperability with different versions.
080:             */
081:            private static final long serialVersionUID = 8235685097881260737L;
082:
083:            /**
084:             * The output coordinate reference system. May be {@code null}.
085:             */
086:            private CoordinateReferenceSystem crs;
087:
088:            /**
089:             * The separator between each coordinate values to be formatted.
090:             */
091:            private String separator;
092:
093:            /**
094:             * The formats to use for formatting. This array's length must be equals
095:             * to the {@linkplain #getCoordinateReferenceSystem coordinate system}'s
096:             * dimension. This array is never {@code null}.
097:             */
098:            private Format[] formats;
099:
100:            /**
101:             * Formatter for units. Will be created only when first needed.
102:             */
103:            private transient UnitFormat unitFormat;
104:
105:            /**
106:             * The type for each value in the {@code formats} array.
107:             * Types are: 0=number, 1=longitude, 2=latitude, 3=other angle,
108:             * 4=date, 5=ellapsed time. This array is never {@code null}.
109:             */
110:            private byte[] types;
111:
112:            /**
113:             * Constants for the {@code types} array.
114:             */
115:            private static final byte LONGITUDE = 1, LATITUDE = 2, ANGLE = 3,
116:                    DATE = 4, TIME = 5;
117:
118:            /**
119:             * The time epochs. Non-null only if at least one ordinate is a date.
120:             */
121:            private long[] epochs;
122:
123:            /**
124:             * Conversions from temporal axis units to milliseconds.
125:             * Non-null only if at least one ordinate is a date.
126:             */
127:            private Converter[] toMillis;
128:
129:            /**
130:             * Dummy field position.
131:             */
132:            private final FieldPosition dummy = new FieldPosition(0);
133:
134:            /**
135:             * The locale for formatting coordinates and numbers.
136:             */
137:            private final Locale locale;
138:
139:            /**
140:             * Constructs a new coordinate format with default locale and a two-dimensional
141:             * {@linkplain DefaultGeographicCRS#WGS84 geographic (WGS 1984)} coordinate reference system.
142:             */
143:            public CoordinateFormat() {
144:                this (Locale.getDefault());
145:            }
146:
147:            /**
148:             * Construct a new coordinate format for the specified locale and a two-dimensional
149:             * {@linkplain DefaultGeographicCRS#WGS84 geographic (WGS 1984)} coordinate reference system.
150:             *
151:             * @param locale The locale for formatting coordinates and numbers.
152:             */
153:            public CoordinateFormat(final Locale locale) {
154:                this (locale, DefaultGeographicCRS.WGS84);
155:            }
156:
157:            /**
158:             * Constructs a new coordinate format for the specified locale and coordinate reference system.
159:             *
160:             * @param locale The locale for formatting coordinates and numbers.
161:             * @param crs    The output coordinate reference system.
162:             */
163:            public CoordinateFormat(final Locale locale,
164:                    final CoordinateReferenceSystem crs) {
165:                this .locale = locale;
166:                this .separator = " ";
167:                setCoordinateReferenceSystem(crs);
168:            }
169:
170:            /**
171:             * Returns the coordinate reference system for points to be formatted.
172:             *
173:             * @return The output coordinate reference system.
174:             */
175:            public CoordinateReferenceSystem getCoordinateReferenceSystem() {
176:                return crs;
177:            }
178:
179:            /**
180:             * Set the coordinate reference system for points to be formatted. The number
181:             * of dimensions must matched the dimension of points to be formatted.
182:             *
183:             * @param crs The new coordinate system.
184:             */
185:            public void setCoordinateReferenceSystem(
186:                    final CoordinateReferenceSystem crs) {
187:                if (CRS.equalsIgnoreMetadata(this .crs, (this .crs = crs))) {
188:                    return;
189:                }
190:                Format numberFormat = null;
191:                Format angleFormat = null;
192:                Format dateFormat = null;
193:                /*
194:                 * Reuses existing formats. It is necessary in order to avoid
195:                 * overwritting any setting done with 'setNumberPattern(...)'
196:                 * or 'setAnglePattern(...)'
197:                 */
198:                if (formats != null) {
199:                    for (int i = formats.length; --i >= 0;) {
200:                        final Format format = formats[i];
201:                        if (format instanceof  NumberFormat) {
202:                            numberFormat = format;
203:                        } else if (format instanceof  AngleFormat) {
204:                            angleFormat = format;
205:                        } else if (format instanceof  DateFormat) {
206:                            dateFormat = format;
207:                        }
208:                    }
209:                }
210:                /*
211:                 * If no CRS were specified, formats everything as numbers. Working with null CRS is
212:                 * sometime useful because null CRS are allowed in DirectPosition according ISO 19107.
213:                 */
214:                if (crs == null) {
215:                    if (numberFormat == null) {
216:                        numberFormat = NumberFormat.getNumberInstance(locale);
217:                    }
218:                    types = new byte[1];
219:                    formats = new Format[] { numberFormat };
220:                    return;
221:                }
222:                /*
223:                 * Creates a new array of 'Format' objects, one for each dimension.
224:                 * The format subclasses are infered from coordinate system axis.
225:                 */
226:                final CoordinateSystem cs = crs.getCoordinateSystem();
227:                epochs = null;
228:                toMillis = null;
229:                formats = new Format[cs.getDimension()];
230:                types = new byte[formats.length];
231:                for (int i = 0; i < formats.length; i++) {
232:                    final Unit unit = cs.getAxis(i).getUnit();
233:                    /////////////////
234:                    ////  Angle  ////
235:                    /////////////////
236:                    if (NonSI.DEGREE_ANGLE.equals(unit)) {
237:                        if (angleFormat == null) {
238:                            angleFormat = new AngleFormat("DD°MM.m'", locale);
239:                        }
240:                        formats[i] = angleFormat;
241:                        final AxisDirection axis = cs.getAxis(i).getDirection()
242:                                .absolute();
243:                        if (AxisDirection.EAST.equals(axis)) {
244:                            types[i] = LONGITUDE;
245:                        } else if (AxisDirection.NORTH.equals(axis)) {
246:                            types[i] = LATITUDE;
247:                        } else {
248:                            types[i] = ANGLE;
249:                        }
250:                        continue;
251:                    }
252:                    ////////////////
253:                    ////  Date  ////
254:                    ////////////////
255:                    if (SI.SECOND.isCompatible(unit)) {
256:                        final Datum datum = CRSUtilities.getDatum(CRSUtilities
257:                                .getSubCRS(crs, i, i + 1));
258:                        if (datum instanceof  TemporalDatum) {
259:                            if (toMillis == null) {
260:                                toMillis = new Converter[formats.length];
261:                                epochs = new long[formats.length];
262:                            }
263:                            toMillis[i] = unit
264:                                    .getConverterTo(DefaultTemporalCRS.MILLISECOND);
265:                            epochs[i] = ((TemporalDatum) datum).getOrigin()
266:                                    .getTime();
267:                            if (dateFormat == null) {
268:                                dateFormat = DateFormat.getDateInstance(
269:                                        DateFormat.DEFAULT, locale);
270:                            }
271:                            formats[i] = dateFormat;
272:                            types[i] = DATE;
273:                            continue;
274:                        }
275:                        types[i] = TIME;
276:                        // Fallthrough: formatted as number for now.
277:                        // TODO: Provide ellapsed time formatting later.
278:                    }
279:                    //////////////////
280:                    ////  Number  ////
281:                    //////////////////
282:                    if (numberFormat == null) {
283:                        numberFormat = NumberFormat.getNumberInstance(locale);
284:                    }
285:                    formats[i] = numberFormat;
286:                    // types[i] default to 0.
287:                }
288:            }
289:
290:            /**
291:             * Returns the separator between each coordinate (number, angle or date).
292:             *
293:             * @since 2.2
294:             */
295:            public String getSeparator() {
296:                return separator;
297:            }
298:
299:            /**
300:             * Set the separator between each coordinate.
301:             *
302:             * @since 2.2
303:             */
304:            public void setSeparator(final String separator) {
305:                this .separator = separator;
306:            }
307:
308:            /**
309:             * Set the pattern for numbers fields.  If some ordinates are formatted as plain number
310:             * (for example in {@linkplain org.geotools.referencing.cs.DefaultCartesianCS cartesian
311:             * coordinate system}), then those numbers will be formatted using this pattern.
312:             *
313:             * @param pattern The number pattern as specified in {@link DecimalFormat}.
314:             */
315:            public void setNumberPattern(final String pattern) {
316:                Format lastFormat = null;
317:                for (int i = 0; i < formats.length; i++) {
318:                    final Format format = formats[i];
319:                    if (format != lastFormat
320:                            && (format instanceof  DecimalFormat)) {
321:                        ((DecimalFormat) format).applyPattern(pattern);
322:                        lastFormat = format;
323:                    }
324:                }
325:            }
326:
327:            /**
328:             * Set the pattern for angles fields. If some ordinates are formatted as angle
329:             * (for example in {@linkplain org.geotools.referencing.cs.DefaultEllipsoidalCS
330:             * ellipsoidal coordinate system}), then those angles will be formatted using
331:             * this pattern.
332:             *
333:             * @param pattern The angle pattern as specified in {@link AngleFormat}.
334:             */
335:            public void setAnglePattern(final String pattern) {
336:                Format lastFormat = null;
337:                for (int i = 0; i < formats.length; i++) {
338:                    final Format format = formats[i];
339:                    if (format != lastFormat && (format instanceof  AngleFormat)) {
340:                        ((AngleFormat) format).applyPattern(pattern);
341:                        lastFormat = format;
342:                    }
343:                }
344:            }
345:
346:            /**
347:             * Set the pattern for dates fields. If some ordinates are formatted as date (for example in
348:             * {@linkplain org.geotools.referencing.cs.DefaultTimeCS time coordinate system}), then
349:             * those dates will be formatted using this pattern.
350:             *
351:             * @param pattern The date pattern as specified in {@link SimpleDateFormat}.
352:             */
353:            public void setDatePattern(final String pattern) {
354:                Format lastFormat = null;
355:                for (int i = 0; i < formats.length; i++) {
356:                    final Format format = formats[i];
357:                    if (format != lastFormat
358:                            && (format instanceof  SimpleDateFormat)) {
359:                        ((SimpleDateFormat) format).applyPattern(pattern);
360:                        lastFormat = format;
361:                    }
362:                }
363:            }
364:
365:            /**
366:             * Set the time zone for dates fields. If some ordinates are formatted as date (for example in
367:             * {@linkplain org.geotools.referencing.cs.DefaultTimeCS time coordinate system}), then
368:             * those dates will be formatted using the specified time zone.
369:             *
370:             * @param timezone The time zone for dates.
371:             */
372:            public void setTimeZone(final TimeZone timezone) {
373:                Format lastFormat = null;
374:                for (int i = 0; i < formats.length; i++) {
375:                    final Format format = formats[i];
376:                    if (format != lastFormat && (format instanceof  DateFormat)) {
377:                        ((DateFormat) format).setTimeZone(timezone);
378:                        lastFormat = format;
379:                    }
380:                }
381:            }
382:
383:            /**
384:             * Returns the format to use for formatting an ordinate at the given dimension.
385:             * The dimension parameter range from 0 inclusive to the
386:             * {@linkplain #getCoordinateReferenceSystem coordinate reference system}'s dimension,
387:             * exclusive. This method returns a direct reference to the internal format; any change
388:             * to the returned {@link Format} object will change the formatting for this
389:             * {@code CoordinateFormat} object.
390:             *
391:             * @param  dimension The dimension for the ordinate to format.
392:             * @return The format for the given dimension.
393:             * @throws IndexOutOfBoundsException if {@code dimension} is out of range.
394:             */
395:            public Format getFormat(final int dimension)
396:                    throws IndexOutOfBoundsException {
397:                return formats[dimension];
398:            }
399:
400:            /**
401:             * Formats a direct position. The position's dimension must matches the
402:             * {@linkplain #getCoordinateReferenceSystem coordinate reference system} dimension.
403:             *
404:             * @param  point The position to format.
405:             * @return The formatted position.
406:             * @throws IllegalArgumentException if this {@code CoordinateFormat}
407:             *         cannot format the given object.
408:             */
409:            public String format(final DirectPosition point) {
410:                return format(point, new StringBuffer(), null).toString();
411:            }
412:
413:            /**
414:             * Formats a direct position and appends the resulting text to a given string buffer.
415:             * The position's dimension must matches the {@linkplain #getCoordinateReferenceSystem
416:             * coordinate reference system} dimension.
417:             *
418:             * @param point      The position to format.
419:             * @param toAppendTo Where the text is to be appended.
420:             * @param position   A {@code FieldPosition} identifying a field in the formatted text,
421:             *                   or {@code null} if none.
422:             * @return The string buffer passed in as {@code toAppendTo}, with formatted text appended.
423:             * @throws IllegalArgumentException if this {@code CoordinateFormat}
424:             *         cannot format the given object.
425:             */
426:            public StringBuffer format(final DirectPosition point,
427:                    final StringBuffer toAppendTo, final FieldPosition position)
428:                    throws IllegalArgumentException {
429:                final int dimension = point.getDimension();
430:                final CoordinateSystem cs;
431:                if (crs != null) {
432:                    if (dimension != formats.length) {
433:                        throw new MismatchedDimensionException(Errors.format(
434:                                ErrorKeys.MISMATCHED_DIMENSION_$3, "point",
435:                                new Integer(dimension), new Integer(
436:                                        formats.length)));
437:                    }
438:                    cs = crs.getCoordinateSystem();
439:                } else {
440:                    cs = null;
441:                }
442:                for (int i = 0; i < dimension; i++) {
443:                    final double value = point.getOrdinate(i);
444:                    final int fi = Math.min(i, formats.length - 1);
445:                    final Object object;
446:                    final byte type = types[fi];
447:                    switch (type) {
448:                    default:
449:                        object = new Double(value);
450:                        break;
451:                    case LONGITUDE:
452:                        object = new Longitude(value);
453:                        break;
454:                    case LATITUDE:
455:                        object = new Latitude(value);
456:                        break;
457:                    case ANGLE:
458:                        object = new Angle(value);
459:                        break;
460:                    case DATE: {
461:                        final CoordinateSystemAxis axis = cs.getAxis(i);
462:                        long offset = Math.round(toMillis[fi].convert(value));
463:                        if (AxisDirection.PAST.equals(axis.getDirection())) {
464:                            offset = -offset;
465:                        }
466:                        object = new Date(epochs[fi] + offset);
467:                        break;
468:                    }
469:                    }
470:                    if (i != 0) {
471:                        toAppendTo.append(separator);
472:                    }
473:                    formats[fi].format(object, toAppendTo, dummy);
474:                    /*
475:                     * If the formatted value is a number, append the units.
476:                     */
477:                    if (type == 0 && cs != null) {
478:                        final Unit unit = cs.getAxis(i).getUnit();
479:                        if (unit != null) {
480:                            if (unitFormat == null) {
481:                                unitFormat = UnitFormat.getInstance();
482:                            }
483:                            final String asText = unitFormat.format(unit);
484:                            if (asText.length() != 0) {
485:                                toAppendTo.append('\u00A0'); // No break space
486:                                toAppendTo.append(unit);
487:                            }
488:                        }
489:                    }
490:                }
491:                return toAppendTo;
492:            }
493:
494:            /**
495:             * Formats a direct position and appends the resulting text to a given string buffer.
496:             * The position's dimension must matches the {@linkplain #getCoordinateReferenceSystem
497:             * coordinate reference system} dimension.
498:             *
499:             * @param object     The {@link DirectPosition} to format.
500:             * @param toAppendTo Where the text is to be appended.
501:             * @param position   A {@code FieldPosition} identifying a field in the formatted text,
502:             *                   or {@code null} if none.
503:             * @return The string buffer passed in as {@code toAppendTo}, with formatted text appended.
504:             * @throws NullPointerException if {@code toAppendTo} is null.
505:             * @throws IllegalArgumentException if this {@code CoordinateFormat}
506:             *         cannot format the given object.
507:             */
508:            public StringBuffer format(final Object object,
509:                    final StringBuffer toAppendTo, final FieldPosition position)
510:                    throws IllegalArgumentException {
511:                if (object instanceof  DirectPosition) {
512:                    return format((DirectPosition) object, toAppendTo, position);
513:                } else {
514:                    throw new IllegalArgumentException(String.valueOf(object));
515:                }
516:            }
517:
518:            /**
519:             * Not yet implemented.
520:             */
521:            public Object parseObject(final String source,
522:                    final ParsePosition position) {
523:                throw new UnsupportedOperationException(
524:                        "DirectPosition parsing not yet implemented.");
525:            }
526:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.