001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2004-2024 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.referencing.cs;
019
020import java.util.Optional;
021import org.opengis.util.CodeList;
022import org.opengis.annotation.UML;
023import org.opengis.geoapi.internal.Vocabulary;
024
025import static org.opengis.annotation.Obligation.*;
026import static org.opengis.annotation.Specification.*;
027
028
029/**
030 * The direction of positive increase in the coordinate value for a coordinate system axis.
031 * This direction is exact in some cases, and is approximate in other cases.
032 *
033 * <p>Some coordinate systems use non-standard orientations.
034 * For example, the first axis in South African grids usually points West, instead of East.
035 * This information is relevant for algorithms converting South African grid coordinates into Lat/Long.</p>
036 *
037 * @author  OGC Topic 2 (for abstract model and documentation)
038 * @author  Martin Desruisseaux (IRD, Geomatys)
039 * @version 3.1
040 * @since   1.0
041 *
042 * @see CoordinateSystemAxis#getDirection()
043 */
044@Vocabulary(capacity=41)
045@UML(identifier="AxisDirection", specification=ISO_19111)
046public final class AxisDirection extends CodeList<AxisDirection> {
047    /**
048     * Serial number for compatibility with different versions.
049     */
050    private static final long serialVersionUID = -4405275475770755714L;
051
052    /**
053     * Unknown or unspecified axis orientation.
054     *
055     * @category Other
056     *
057     * @deprecated Replaced by {@link #UNSPECIFIED} in ISO 19111:2019.
058     */
059    @Deprecated(since = "3.1")
060    @UML(identifier="CS_AxisOrientationEnum.CS_AO_Other", obligation=CONDITIONAL, specification=OGC_01009)
061    public static final AxisDirection OTHER = new AxisDirection("OTHER");
062
063    /**
064     * Axis positive direction is north.
065     * In a geographic or projected <abbr>CRS</abbr>, north is defined through the geodetic reference frame.
066     * In an engineering <abbr>CRS</abbr>, north may be defined with respect to an engineering object
067     * rather than a geographical direction.
068     *
069     * @category Rose
070     */
071    @UML(identifier="north", obligation=CONDITIONAL, specification=ISO_19111)
072    public static final AxisDirection NORTH = new AxisDirection("NORTH");
073
074    /**
075     * Axis positive direction is approximately north-north-east.
076     *
077     * @category Rose
078     */
079    @UML(identifier="northNorthEast", obligation=CONDITIONAL, specification=ISO_19111)
080    public static final AxisDirection NORTH_NORTH_EAST = new AxisDirection("NORTH_NORTH_EAST");
081
082    /**
083     * Axis positive direction is approximately north-east.
084     *
085     * @category Rose
086     */
087    @UML(identifier="northEast", obligation=CONDITIONAL, specification=ISO_19111)
088    public static final AxisDirection NORTH_EAST = new AxisDirection("NORTH_EAST");
089
090    /**
091     * Axis positive direction is approximately east-north-east.
092     *
093     * @category Rose
094     */
095    @UML(identifier="eastNorthEast", obligation=CONDITIONAL, specification=ISO_19111)
096    public static final AxisDirection EAST_NORTH_EAST = new AxisDirection("EAST_NORTH_EAST");
097
098    /**
099     * Axis positive direction is π/2 radians clockwise from north.
100     * This is usually used for grid <var>X</var> coordinates and for longitude.
101     *
102     * @category Rose
103     */
104    @UML(identifier="east", obligation=CONDITIONAL, specification=ISO_19111)
105    public static final AxisDirection EAST = new AxisDirection("EAST");
106
107    /**
108     * Axis positive direction is approximately east-south-east.
109     *
110     * @category Rose
111     */
112    @UML(identifier="eastSouthEast", obligation=CONDITIONAL, specification=ISO_19111)
113    public static final AxisDirection EAST_SOUTH_EAST = new AxisDirection("EAST_SOUTH_EAST");
114
115    /**
116     * Axis positive direction is approximately south-east.
117     *
118     * @category Rose
119     */
120    @UML(identifier="southEast", obligation=CONDITIONAL, specification=ISO_19111)
121    public static final AxisDirection SOUTH_EAST = new AxisDirection("SOUTH_EAST");
122
123    /**
124     * Axis positive direction is approximately south-south-east.
125     *
126     * @category Rose
127     */
128    @UML(identifier="southSouthEast", obligation=CONDITIONAL, specification=ISO_19111)
129    public static final AxisDirection SOUTH_SOUTH_EAST = new AxisDirection("SOUTH_SOUTH_EAST");
130
131    /**
132     * Axis positive direction is π radians clockwise from north.
133     *
134     * @category Rose
135     */
136    @UML(identifier="south", obligation=CONDITIONAL, specification=ISO_19111)
137    public static final AxisDirection SOUTH = new AxisDirection("SOUTH", NORTH);
138
139    /**
140     * Axis positive direction is approximately south-south-west.
141     *
142     * @category Rose
143     */
144    @UML(identifier="southSouthWest", obligation=CONDITIONAL, specification=ISO_19111)
145    public static final AxisDirection SOUTH_SOUTH_WEST = new AxisDirection("SOUTH_SOUTH_WEST", NORTH_NORTH_EAST);
146
147    /**
148     * Axis positive direction is approximately south-west.
149     *
150     * @category Rose
151     */
152    @UML(identifier="southWest", obligation=CONDITIONAL, specification=ISO_19111)
153    public static final AxisDirection SOUTH_WEST = new AxisDirection("SOUTH_WEST", NORTH_EAST);
154
155    /**
156     * Axis positive direction is approximately west-south-west.
157     *
158     * @category Rose
159     */
160    @UML(identifier="westSouthWest", obligation=CONDITIONAL, specification=ISO_19111)
161    public static final AxisDirection WEST_SOUTH_WEST = new AxisDirection("WEST_SOUTH_WEST", EAST_NORTH_EAST);
162
163    /**
164     * Axis positive direction is 3π/2 radians clockwise from north.
165     * This is usually used for Grid X coordinates and Longitude.
166     *
167     * @category Rose
168     */
169    @UML(identifier="west", obligation=CONDITIONAL, specification=ISO_19111)
170    public static final AxisDirection WEST = new AxisDirection("WEST", EAST);
171
172    /**
173     * Axis positive direction is approximately west-north-west.
174     *
175     * @category Rose
176     */
177    @UML(identifier="westNorthWest", obligation=CONDITIONAL, specification=ISO_19111)
178    public static final AxisDirection WEST_NORTH_WEST = new AxisDirection("WEST_NORTH_WEST", EAST_SOUTH_EAST);
179
180    /**
181     * Axis positive direction is approximately north-west.
182     *
183     * @category Rose
184     */
185    @UML(identifier="northWest", obligation=CONDITIONAL, specification=ISO_19111)
186    public static final AxisDirection NORTH_WEST = new AxisDirection("NORTH_WEST", SOUTH_EAST);
187
188    /**
189     * Axis positive direction is approximately north-north-west.
190     *
191     * @category Rose
192     */
193    @UML(identifier="northNorthWest", obligation=CONDITIONAL, specification=ISO_19111)
194    public static final AxisDirection NORTH_NORTH_WEST = new AxisDirection("NORTH_NORTH_WEST", SOUTH_SOUTH_EAST);
195
196    /**
197     * Axis positive direction is up relative to gravity.
198     * This is used for {@linkplain VerticalCS vertical coordinate systems}.
199     *
200     * @category Vertical
201     */
202    @UML(identifier="up", obligation=CONDITIONAL, specification=ISO_19111)
203    public static final AxisDirection UP = new AxisDirection("UP");
204
205    /**
206     * Axis positive direction is down relative to gravity.
207     * This is used for {@linkplain VerticalCS vertical coordinate systems}.
208     *
209     * @category Vertical
210     */
211    @UML(identifier="down", obligation=CONDITIONAL, specification=ISO_19111)
212    public static final AxisDirection DOWN = new AxisDirection("DOWN", UP);
213
214    /**
215     * Axis positive direction is toward geocentric <var>X</var>.
216     * This is the direction in the equatorial plane from the center of the modeled planet
217     * towards the intersection of the equator with the prime meridian.
218     *
219     * @category Geocentric
220     */
221    @UML(identifier="geocentricX", obligation=CONDITIONAL, specification=ISO_19111)
222    public static final AxisDirection GEOCENTRIC_X = new AxisDirection("GEOCENTRIC_X");
223
224    /**
225     * Axis positive direction is toward geocentric <var>Y</var>.
226     * This is the direction in the equatorial plane from the center of the modeled planet
227     * towards the intersection of the equator and the meridian π/2 radians eastwards from the prime meridian.
228     *
229     * @category Geocentric
230     */
231    @UML(identifier="geocentricY", obligation=CONDITIONAL, specification=ISO_19111)
232    public static final AxisDirection GEOCENTRIC_Y = new AxisDirection("GEOCENTRIC_Y");
233
234    /**
235     * Axis positive direction is toward geocentric <var>Z</var>.
236     * This is the direction from the center of the modeled planet
237     * parallel to its rotation axis and towards its north pole.
238     *
239     * @category Geocentric
240     */
241    @UML(identifier="geocentricZ", obligation=CONDITIONAL, specification=ISO_19111)
242    public static final AxisDirection GEOCENTRIC_Z = new AxisDirection("GEOCENTRIC_Z");
243
244    /**
245     * Axis positive direction is towards higher pixel column.
246     *
247     * @category Image
248     */
249    @UML(identifier="columnPositive", obligation=CONDITIONAL, specification=ISO_19111)
250    public static final AxisDirection COLUMN_POSITIVE = new AxisDirection("COLUMN_POSITIVE");
251
252    /**
253     * Axis positive direction is towards lower pixel column.
254     *
255     * @category Image
256     */
257    @UML(identifier="columnNegative", obligation=CONDITIONAL, specification=ISO_19111)
258    public static final AxisDirection COLUMN_NEGATIVE = new AxisDirection("COLUMN_NEGATIVE", COLUMN_POSITIVE);
259
260    /**
261     * Axis positive direction is towards higher pixel row.
262     *
263     * @category Image
264     */
265    @UML(identifier="rowPositive", obligation=CONDITIONAL, specification=ISO_19111)
266    public static final AxisDirection ROW_POSITIVE = new AxisDirection("ROW_POSITIVE");
267
268    /**
269     * Axis positive direction is towards lower pixel row.
270     *
271     * @category Image
272     */
273    @UML(identifier="rowNegative", obligation=CONDITIONAL, specification=ISO_19111)
274    public static final AxisDirection ROW_NEGATIVE = new AxisDirection("ROW_NEGATIVE", ROW_POSITIVE);
275
276    /**
277     * Axis positive direction is right in display.
278     *
279     * @category Display
280     */
281    @UML(identifier="displayRight", obligation=CONDITIONAL, specification=ISO_19111)
282    public static final AxisDirection DISPLAY_RIGHT = new AxisDirection("DISPLAY_RIGHT");
283
284    /**
285     * Axis positive direction is left in display.
286     *
287     * @category Display
288     */
289    @UML(identifier="displayLeft", obligation=CONDITIONAL, specification=ISO_19111)
290    public static final AxisDirection DISPLAY_LEFT = new AxisDirection("DISPLAY_LEFT", DISPLAY_RIGHT);
291
292    /**
293     * Axis positive direction is towards top of approximately vertical display surface.
294     *
295     * @category Display
296     */
297    @UML(identifier="displayUp", obligation=CONDITIONAL, specification=ISO_19111)
298    public static final AxisDirection DISPLAY_UP = new AxisDirection("DISPLAY_UP");
299
300    /**
301     * Axis positive direction is towards bottom of approximately vertical display surface.
302     *
303     * @category Display
304     */
305    @UML(identifier="displayDown", obligation=CONDITIONAL, specification=ISO_19111)
306    public static final AxisDirection DISPLAY_DOWN = new AxisDirection("DISPLAY_DOWN", DISPLAY_UP);
307
308    /**
309     * Axis positive direction is forward.
310     * For an observer at the center of the object this will be towards its front, bow or nose.
311     *
312     * @category Engineering
313     * @since 3.1
314     */
315    @UML(identifier="forward", obligation=CONDITIONAL, specification=ISO_19111)
316    public static final AxisDirection FORWARD = new AxisDirection("FORWARD");
317
318    /**
319     * Axis positive direction is aft.
320     * For an observer at the center of the object this will be towards its back, stern or tail.
321     *
322     * @category Engineering
323     * @since 3.1
324     */
325    @UML(identifier="aft", obligation=CONDITIONAL, specification=ISO_19111)
326    public static final AxisDirection AFT = new AxisDirection("AFT", FORWARD);
327
328    /**
329     * Axis positive direction is port.
330     * For an observer looking forward from the center of the object this will be towards its left.
331     *
332     * @category Engineering
333     * @since 3.1
334     */
335    @UML(identifier="port", obligation=CONDITIONAL, specification=ISO_19111)
336    public static final AxisDirection PORT = new AxisDirection("PORT");
337
338    /**
339     * Axis positive direction is starboard.
340     * For an observer looking forward from the center of the object this will be towards its right.
341     *
342     * @category Engineering
343     * @since 3.1
344     */
345    @UML(identifier="starboard", obligation=CONDITIONAL, specification=ISO_19111)
346    public static final AxisDirection STARBOARD = new AxisDirection("STARBOARD", PORT);
347
348    /**
349     * Axis positive direction is clockwise from a specified direction.
350     *
351     * @category Engineering
352     * @since 3.1
353     */
354    @UML(identifier="clockwise", obligation=CONDITIONAL, specification=ISO_19111)
355    public static final AxisDirection CLOCKWISE = new AxisDirection("CLOCKWISE");
356
357    /**
358     * Axis positive direction is counter clockwise from a specified direction.
359     *
360     * @category Engineering
361     * @since 3.1
362     */
363    @UML(identifier="counterClockwise", obligation=CONDITIONAL, specification=ISO_19111)
364    public static final AxisDirection COUNTER_CLOCKWISE = new AxisDirection("COUNTER_CLOCKWISE", CLOCKWISE);
365
366    /**
367     * Axis positive direction is towards the object.
368     *
369     * @category Engineering
370     * @since 3.1
371     */
372    @UML(identifier="towards", obligation=CONDITIONAL, specification=ISO_19111)
373    public static final AxisDirection TOWARDS = new AxisDirection("TOWARDS");
374
375    /**
376     * Axis positive direction is away from the object.
377     *
378     * @category Engineering
379     * @since 3.1
380     */
381    @UML(identifier="awayFrom", obligation=CONDITIONAL, specification=ISO_19111)
382    public static final AxisDirection AWAY_FROM = new AxisDirection("AWAY_FROM", TOWARDS);
383
384    /**
385     * Axis positive direction is towards the future.
386     * This is used for {@linkplain TimeCS temporal coordinate systems}.
387     *
388     * @category Temporal
389     */
390    @UML(identifier="future", obligation=CONDITIONAL, specification=ISO_19111)
391    public static final AxisDirection FUTURE = new AxisDirection("FUTURE");
392
393    /**
394     * Axis positive direction is towards the past.
395     * This is used for {@linkplain TimeCS temporal coordinate systems}.
396     *
397     * @category Temporal
398     */
399    @UML(identifier="past", obligation=CONDITIONAL, specification=ISO_19111)
400    public static final AxisDirection PAST = new AxisDirection("PAST", FUTURE);
401
402    /**
403     * Axis positive direction is unspecified.
404     *
405     * @category Other
406     * @since 3.1
407     */
408    @UML(identifier="unspecified", obligation=CONDITIONAL, specification=ISO_19111)
409    public static final AxisDirection UNSPECIFIED = new AxisDirection("UNSPECIFIED");
410    static {
411        UNSPECIFIED.opposite = UNSPECIFIED;
412    }
413
414    /**
415     * The direction of negative coordinate values, or {@code null} if unknown.
416     */
417    private AxisDirection opposite;
418
419    /**
420     * Constructs an element of the given name.
421     *
422     * @param name  the name of the new element. This name shall not be in use by another element of this type.
423     */
424    private AxisDirection(final String name) {
425        super(name);
426    }
427
428    /**
429     * Constructs an element of the given name.
430     *
431     * @param name  the name of the new element. This name shall not be in use by another element of this type.
432     * @param opposite  the direction of negative coordinate values.
433     */
434    private AxisDirection(final String name, final AxisDirection opposite) {
435        super(name);
436        this.opposite = opposite;
437        opposite.opposite = this;
438    }
439
440    /**
441     * Returns the direction of negative coordinate values.
442     * For example, the opposite of {@link #NORTH} is {@link #SOUTH} and the opposite of {@link #FUTURE} is {@link #PAST}.
443     * The opposite of the opposite (if present) is always {@code this}.
444     *
445     * @return direction of negative coordinate values.
446     *
447     * @since 3.1
448     */
449    public Optional<AxisDirection> opposite() {
450        return Optional.ofNullable(opposite);
451    }
452
453    /**
454     * Returns the list of {@code AxisDirection}s.
455     *
456     * @return the list of codes declared in the current JVM.
457     */
458    public static AxisDirection[] values() {
459        return values(AxisDirection.class);
460    }
461
462    /**
463     * Returns the list of codes of the same kind as this code list element.
464     * Invoking this method is equivalent to invoking {@link #values()}, except that
465     * this method can be invoked on an instance of the parent {@code CodeList} class.
466     *
467     * @return all code {@linkplain #values() values} for this code list.
468     */
469    @Override
470    public AxisDirection[] family() {
471        return values();
472    }
473
474    /**
475     * Returns the axis direction that matches the given string, or returns a new one if none match it.
476     * This methods returns the first instance (in declaration order) for which the {@linkplain #name() name}
477     * is {@linkplain String#equalsIgnoreCase(String) equals, ignoring case}, to the given name.
478     * If no existing instance is found, then a new one is created for the given name.
479     *
480     * @param  code  the name of the code to fetch or to create.
481     * @return a code matching the given name.
482     */
483    public static AxisDirection valueOf(String code) {
484        return valueOf(AxisDirection.class, code, AxisDirection::new).get();
485    }
486}