001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/cs/AxisOrientation.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/exse/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 It has been implemented within SEAGIS - An OpenSource implementation of OpenGIS specification
012 (C) 2001, Institut de Recherche pour le D�veloppement (http://sourceforge.net/projects/seagis/)
013 SEAGIS Contacts: Surveillance de l'Environnement Assist�e par Satellite
014 Institut de Recherche pour le D�veloppement / US-Espace
015 mailto:seasnet@teledetection.fr
016
017
018 This library is free software; you can redistribute it and/or
019 modify it under the terms of the GNU Lesser General Public
020 License as published by the Free Software Foundation; either
021 version 2.1 of the License, or (at your option) any later version.
022
023 This library is distributed in the hope that it will be useful,
024 but WITHOUT ANY WARRANTY; without even the implied warranty of
025 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
026 Lesser General Public License for more details.
027
028 You should have received a copy of the GNU Lesser General Public
029 License along with this library; if not, write to the Free Software
030 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
031
032 Contact:
033
034 Andreas Poth
035 lat/lon GmbH
036 Aennchenstr. 19
037 53115 Bonn
038 Germany
039 E-Mail: poth@lat-lon.de
040
041 Klaus Greve
042 Department of Geography
043 University of Bonn
044 Meckenheimer Allee 166
045 53115 Bonn
046 Germany
047 E-Mail: klaus.greve@uni-bonn.de
048
049
050 ---------------------------------------------------------------------------*/
051 package org.deegree.model.csct.cs;
052
053 // OpenGIS dependencies
054 import java.io.ObjectStreamException;
055 import java.util.Locale;
056 import java.util.NoSuchElementException;
057
058 import javax.media.jai.EnumeratedParameter;
059
060 import org.deegree.model.csct.resources.css.ResourceKeys;
061 import org.deegree.model.csct.resources.css.Resources;
062
063 /**
064 * Orientation of axis. Some coordinate systems use non-standard orientations. For example, the
065 * first axis in South African grids usually points West, instead of East. This information is
066 * obviously relevant for algorithms converting South African grid coordinates into Lat/Long. <br>
067 * <br>
068 * The <em>natural ordering</em> for axis orientations is defined as (EAST-WEST), (NORTH-SOUTH),
069 * (UP-DOWN), (FUTURE-PAST) and OTHER, which is the ordering for a (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>)
070 * coordinate system. This means that when an array of <code>AxisOrientation</code>s is sorted
071 * using {@link java.util.Arrays#sort(Object[])}, EAST and WEST orientations will appears first.
072 * NORTH and SOUTH will be next, followed by UP and DOWN, etc.
073 *
074 * Care should be exercised if <code>AxisOrientation</code>s are to be used as keys in a sorted
075 * map or elements in a sorted set, as <code>AxisOrientation</code>'s natural ordering is
076 * inconsistent with equals. See {@link java.lang.Comparable}, {@link java.util.SortedMap} or
077 * {@link java.util.SortedSet} for more information.
078 *
079 * @version 1.00
080 * @author OpenGIS (www.opengis.org)
081 * @author Martin Desruisseaux
082 *
083 * @author last edited by: $Author: bezema $
084 *
085 * @version $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $
086 *
087 * @see "org.opengis.cs.CS_AxisOrientationEnum"
088 */
089 public final class AxisOrientation extends EnumeratedParameter implements Comparable {
090 /**
091 * Serial number for interoperability with different versions.
092 */
093 private static final long serialVersionUID = 4649182002820021468L;
094
095 /**
096 * Unknown or unspecified axis orientation. This can be used for local or fitted coordinate
097 * systems.
098 */
099 public static final int CS_AO_Other = 0;
100
101 /**
102 * Increasing ordinates values go North. This is usually used for Grid Y coordinates and
103 * Latitude.
104 */
105 public static final int CS_AO_North = 1;
106
107 /**
108 * Increasing ordinates values go South. This is rarely used.
109 */
110 public static final int CS_AO_South = 2;
111
112 /**
113 * Increasing ordinates values go East. This is rarely used.
114 */
115 public static final int CS_AO_East = 3;
116
117 /**
118 * Increasing ordinates values go West. This is usually used for Grid X coordinates and
119 * Longitude.
120 */
121 public static final int CS_AO_West = 4;
122
123 /**
124 * Increasing ordinates values go up. This is used for vertical coordinate systems.
125 */
126 public static final int CS_AO_Up = 5;
127
128 /**
129 * Increasing ordinates values go down. This is used for vertical coordinate systems.
130 */
131 public static final int CS_AO_Down = 6;
132
133 /**
134 * Unknown or unspecified axis orientation. This can be used for local or fitted coordinate
135 * systems.
136 *
137 * @see "org.opengis.cs.CS_AxisOrientationEnum#CS_AO_Other"
138 */
139 public static final AxisOrientation OTHER = new AxisOrientation( "OTHER", CS_AO_Other,
140 ResourceKeys.OTHER );
141
142 /**
143 * Increasing ordinates values go North. This is usually used for Grid Y coordinates and
144 * Latitude.
145 *
146 * @see "org.opengis.cs.CS_AxisOrientationEnum#CS_AO_North"
147 */
148 public static final AxisOrientation NORTH = new AxisOrientation( "NORTH", CS_AO_North,
149 ResourceKeys.NORTH );
150
151 /**
152 * Increasing ordinates values go South.
153 *
154 * @see "org.opengis.cs.CS_AxisOrientationEnum#CS_AO_South"
155 */
156 public static final AxisOrientation SOUTH = new AxisOrientation( "SOUTH", CS_AO_South,
157 ResourceKeys.SOUTH );
158
159 /**
160 * Increasing ordinates values go East. This is usually used for Grid X coordinates and
161 * Longitude.
162 *
163 * @see "org.opengis.cs.CS_AxisOrientationEnum#CS_AO_East"
164 */
165 public static final AxisOrientation EAST = new AxisOrientation( "EAST", CS_AO_East,
166 ResourceKeys.EAST );
167
168 /**
169 * Increasing ordinates values go West.
170 *
171 * @see "org.opengis.cs.CS_AxisOrientationEnum#CS_AO_West"
172 */
173 public static final AxisOrientation WEST = new AxisOrientation( "WEST", CS_AO_West,
174 ResourceKeys.WEST );
175
176 /**
177 * Increasing ordinates values go up. This is used for vertical coordinate systems.
178 *
179 * @see "org.opengis.cs.CS_AxisOrientationEnum#CS_AO_Up"
180 */
181 public static final AxisOrientation UP = new AxisOrientation( "UP", CS_AO_Up, ResourceKeys.UP );
182
183 /**
184 * Increasing ordinates values go down. This is used for vertical coordinate systems.
185 *
186 * @see "org.opengis.cs.CS_AxisOrientationEnum#CS_AO_Down"
187 */
188 public static final AxisOrientation DOWN = new AxisOrientation( "DOWN", CS_AO_Down,
189 ResourceKeys.DOWN );
190
191 /**
192 * Increasing time go toward future. This is used for temporal axis.
193 */
194 public static final AxisOrientation FUTURE = new AxisOrientation( "FUTURE", 7,
195 ResourceKeys.FUTURE );
196
197 /**
198 * Increasing time go toward past. This is used for temporal axis.
199 */
200 public static final AxisOrientation PAST = new AxisOrientation( "PAST", 8, ResourceKeys.PAST );
201
202 /**
203 * The last paired value. Paired value are NORTH-SOUTH, EAST-WEST, UP-DOWN, FUTURE-PAST.
204 */
205 private static final int LAST_PAIRED_VALUE = 8;
206
207 /**
208 * Axis orientations by value. Used to canonicalize after deserialization.
209 */
210 private static final AxisOrientation[] ENUMS = { OTHER, NORTH, SOUTH, EAST, WEST, UP, DOWN,
211 FUTURE, PAST };
212
213 /**
214 * The axis order. Used for {@link #compareTo} implementation.
215 */
216 private static final AxisOrientation[] ORDER = { EAST, NORTH, UP, FUTURE };
217
218 /**
219 * Resource key, used for building localized name. This key doesn't need to be serialized, since
220 * {@link #readResolve} canonicalize enums according their {@link #value}. Furthermore, its
221 * value is implementation-dependent (which is an other raison why it should not be serialized).
222 */
223 private transient final int key;
224
225 /**
226 * Construct a new enum with the specified value.
227 */
228 private AxisOrientation( final String name, final int value, final int key ) {
229 super( name, value );
230 this.key = key;
231 }
232
233 /**
234 * Return the enum for the specified value. This method is provided for compatibility with
235 * {@link "org.opengis.cs.CS_AxisOrientationEnum"}.
236 *
237 * @param value
238 * The enum value.
239 * @return The enum for the specified value.
240 * @throws NoSuchElementException
241 * if there is no enum for the specified value.
242 */
243 public static AxisOrientation getEnum( final int value )
244 throws NoSuchElementException {
245 if ( value >= 0 && value < ENUMS.length )
246 return ENUMS[value];
247 throw new NoSuchElementException( String.valueOf( value ) );
248 }
249
250 /**
251 * Returns this enum's name in the specified locale. If no name is available for the specified
252 * locale, a default one will be used.
253 *
254 * @param locale
255 * The locale, or <code>null</code> for the default locale.
256 * @return Enum's name in the specified locale.
257 */
258 public String getName( final Locale locale ) {
259 return Resources.getResources( locale ).getString( key );
260 }
261
262 /**
263 * Returns the opposite orientation of this axis. The opposite of North is South, and the
264 * opposite of South is North. The same apply to East-West, Up-Down and Future-Past. Other axis
265 * orientation are returned inchanged.
266 *
267 * @return the opposite orientation of this axis. The opposite of North is South, and the
268 * opposite of South is North. The same apply to East-West, Up-Down and Future-Past.
269 * Other axis orientation are returned inchanged.
270 */
271 public AxisOrientation inverse() {
272 final int value = getValue() - 1;
273 if ( value >= 0 && value < LAST_PAIRED_VALUE ) {
274 return ENUMS[( value ^ 1 ) + 1];
275 }
276 return this;
277 }
278
279 /**
280 * Returns the "absolute" orientation of this axis. This "absolute" operation is similar to the
281 * <code>Math.abs(int)</code> method in that "negative" orientation (<code>SOUTH</code>,
282 * <code>WEST</code>, <code>DOWN</code>, <code>PAST</code>) are changed for their
283 * positive counterpart (<code>NORTH</code>, <code>EAST</code>, <code>UP</code>,
284 * <code>FUTURE</code>). More specifically, the following conversion table is applied. <br>
285 * <table align="center" cellpadding="3" border="1" bgcolor="F4F8FF">
286 * <tr bgcolor="#B9DCFF">
287 * <th> Orientation </th>
288 * <th> Absolute value </th>
289 * </tr>
290 * <tr align="center">
291 * <td>NORTH</td>
292 * <td>NORTH</td>
293 * </tr>
294 * <tr align="center">
295 * <td>SOUTH</td>
296 * <td>NORTH</td>
297 * </tr>
298 * <tr align="center">
299 * <td>EAST</td>
300 * <td>EAST</td>
301 * </tr>
302 * <tr align="center">
303 * <td>WEST</td>
304 * <td>EAST</td>
305 * </tr>
306 * <tr align="center">
307 * <td>UP</td>
308 * <td>UP</td>
309 * </tr>
310 * <tr align="center">
311 * <td>DOWN</td>
312 * <td>UP</td>
313 * </tr>
314 * <tr align="center">
315 * <td>FUTURE</td>
316 * <td>FUTURE</td>
317 * </tr>
318 * <tr align="center">
319 * <td>PAST</td>
320 * <td>FUTURE</td>
321 * </tr>
322 * <tr align="center">
323 * <td>OTHER</td>
324 * <td>OTHER</td>
325 * </tr>
326 * </table>
327 *
328 * @return the "absolute" orientation of this axis.
329 */
330 public AxisOrientation absolute() {
331 final int value = getValue() - 1;
332 if ( value >= 0 && value < LAST_PAIRED_VALUE ) {
333 return ENUMS[( value & ~1 ) + 1];
334 }
335 return this;
336 }
337
338 /**
339 * Compares this <code>AxisOrientation</code> with the specified orientation. The
340 * <em>natural ordering</em> is defined as (EAST-WEST), (NORTH-SOUTH), (UP-DOWN),
341 * (FUTURE-PAST) and OTHER, which is the ordering for a (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>)
342 * coordinate system. Two <code>AxisOrientation</code> that are among the same axis but with
343 * an opposite direction (e.g. EAST vs WEST) are considered equal by this method.
344 *
345 * @param ao
346 * An <code>AxisOrientation</code> object to be compared with.
347 * @return
348 * @throws ClassCastException
349 * if <code>ao</code> is not an <code>AxisOrientation</code> object.
350 */
351 public int compareTo( final Object ao ) {
352 final AxisOrientation that = (AxisOrientation) ao;
353 final int thisOrder = this.absolute().getOrder();
354 final int thatOrder = that.absolute().getOrder();
355 if ( thisOrder > thatOrder )
356 return +1;
357 if ( thisOrder < thatOrder )
358 return -1;
359 return 0;
360 }
361
362 /**
363 * Returns the order for this axis orientation (i.e. the index in the {@link #ORDER} table).
364 */
365 private int getOrder() {
366 int i;
367 for ( i = 0; i < ORDER.length; i++ )
368 if ( equals( ORDER[i] ) )
369 break;
370 return i;
371 }
372
373 /**
374 * Use a single instance of {@link AxisOrientation} after deserialization. It allow client code
375 * to test <code>enum1==enum2</code> instead of <code>enum1.equals(enum2)</code>.
376 *
377 * @return A single instance of this enum.
378 * @throws ObjectStreamException
379 * is deserialization failed.
380 */
381 private Object readResolve() {
382 final int value = getValue();
383 if ( value >= 0 && value < ENUMS.length ) {
384 return ENUMS[value]; // Canonicalize
385 }
386 return ENUMS[0]; // Collapse unknow value to a single canonical one
387 }
388 }