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 }