001    /*
002     *    GeoAPI - Java interfaces for OGC/ISO standards
003     *    http://www.geoapi.org
004     *
005     *    Copyright (C) 2005-2013 Open Geospatial Consortium, Inc.
006     *    All Rights Reserved. http://www.opengeospatial.org/ogc/legal
007     *
008     *    Permission to use, copy, and modify this software and its documentation, with
009     *    or without modification, for any purpose and without fee or royalty is hereby
010     *    granted, provided that you include the following on ALL copies of the software
011     *    and documentation or portions thereof, including modifications, that you make:
012     *
013     *    1. The full text of this NOTICE in a location viewable to users of the
014     *       redistributed or derivative work.
015     *    2. Notice of any changes or modifications to the OGC files, including the
016     *       date changes were made.
017     *
018     *    THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE
019     *    NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
020     *    TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
021     *    THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
022     *    PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
023     *
024     *    COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
025     *    CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
026     *
027     *    The name and trademarks of copyright holders may NOT be used in advertising or
028     *    publicity pertaining to the software without specific, written prior permission.
029     *    Title to copyright in this software and any associated documentation will at all
030     *    times remain with copyright holders.
031     */
032    package org.opengis.coverage.grid;
033    
034    import java.util.List;
035    import java.util.ArrayList;
036    
037    import org.opengis.util.CodeList;
038    import org.opengis.annotation.UML;
039    
040    import static org.opengis.annotation.Obligation.*;
041    import static org.opengis.annotation.Specification.*;
042    
043    
044    /**
045     * Specifies the order in which attribute value records are assigned to {@linkplain GridPoint grid points}.
046     * There are several sequencing rules based on incrementing - or decrementing - grid coordinate values in
047     * a simple fashion. More complex space filling curves can also be used. Space filling curves are generated
048     * by progressively subdividing a space in a regular way and connecting the elements resulting from each
049     * subdivision according to some rule. They can be used to generate a grid, but they can also be used to
050     * assign an ordering to the grid points or grid cells in a separately defined grid. They lend themselves
051     * more readily than simple incrementing methods to sequencing in grids that have irregular shapes or cells
052     * of variable size.
053     * <p>
054     * In every case, ordering of the grid cells starts by incrementing coordinates along one grid axis.
055     * At some point in the process, it begins to increment coordinates along a second grid axis, then a
056     * third, and so on until it has progressed in the direction of each of the grid axes. The attribute
057     * {@linkplain SequenceRule#getScanDirection scan direction} provides a list of signed axis names
058     * that identifies the order in which scanning takes place. The list may include an additional element
059     * to support interleaving of feature attribute values.
060     * <p>
061     * Ordering is continuous if consecutive pairs of grid cells in the sequence are maximally connected.
062     * It is semicontinuous if consecutive pairs of grid cells are connected, but less than maximally
063     * connected, and discontinuous if consecutive pairs of cells are not connected.
064     * <p>
065     * <b>Example:</b> In the two dimensional case, a cell is connected to the 8 cells with which it
066     * shares at least one corner. It is maximally connected to the 4 cells with which it shares an
067     * edge and two corners. In the three dimensional case, a cell is maximally connected to those
068     * cells with which it shares a face.
069     *
070     * @version ISO 19123:2004
071     * @author  Wim Koolhoven
072     * @author  Martin Schouwenburg
073     * @author  Martin Desruisseaux (IRD)
074     * @since   GeoAPI 2.1
075     */
076    @UML(identifier="CV_SequenceType", specification=ISO_19123)
077    public class SequenceType extends CodeList<SequenceType> {
078        /**
079         * Serial number for compatibility with different versions.
080         */
081        private static final long serialVersionUID = -6231205465579495566L;
082    
083        /**
084         * List of all enumerations of this type.
085         * Must be declared before any enum declaration.
086         */
087        private static final List<SequenceType> VALUES = new ArrayList<SequenceType>(6);
088    
089        /**
090         * Feature attribute value records are assigned to consecutive grid points along a single grid line
091         * parallel to the first grid axis listed in {@linkplain SequenceRule#getScanDirection scan direction}.
092         * Once scanning of that row is complete, assignment of feature attribute value records steps to another
093         * grid line parallel to the first, and continues to step from grid line to grid line in a direction parallel
094         * to the second axis. If the grid is 3-dimensional, the sequencing process completes the assignment of feature
095         * attribute value records to all grid points in one plane, then steps to another plane, then continues stepping
096         * from plane to plane in a direction parallel to the third axis of the grid. The process can be extended to any
097         * number of axes. Linear scanning is continuous only along a single grid line.
098         *
099         * <center><img src="doc-files/LinearScanning.png"></center>
100         */
101        @UML(identifier="Linear scanning", obligation=CONDITIONAL, specification=ISO_19123)
102        public static final SequenceType LINEAR = new SequenceType("LINEAR");
103    
104        /**
105         * A variant of {@linkplain #LINEAR linear} scanning, in which the direction of the scan is reversed
106         * on alternate grid lines. In the case of a 3-dimensional grid, it will also be reversed in alternate
107         * planes. Boustrophedonic scanning is continuous.
108         * <p>
109         * <b>NOTE:</b> Boustrophedonic scanning is also known as byte-offset scanning.
110         *
111         * <center><img src="doc-files/BoustrophedonicScanning.png"></center>
112         */
113        @UML(identifier="Boustrophedonic scanning", obligation=CONDITIONAL, specification=ISO_19123)
114        public static final SequenceType BOUSTROPHEDONIC = new SequenceType("BOUSTROPHEDONIC");
115    
116        /**
117         * Cantor-diagonal scanning, also called zigzag scanning, orders the grid points in alternating
118         * directions along parallel diagonals of the grid. The scan pattern is affected by the direction
119         * of first step. Like linear scanning, Cantor-diagonal scanning can be extended to grids of three
120         * or more dimensions by repeating the scan pattern in consecutive planes. Cantor-diagonal scanning
121         * is semi-continuous within a single plane.
122         *
123         * <center><img src="doc-files/CantorDiagonalScanning.png"></center>
124         */
125        @UML(identifier="Cantor-diagonal scanning", obligation=CONDITIONAL, specification=ISO_19123)
126        public static final SequenceType CANTOR_DIAGONAL = new SequenceType("CANTOR_DIAGONAL");
127    
128        /**
129         * Spiral scanning can begin either at the centre of the grid (outward spiral), or at a corner
130         * (inward spiral). Like {@linkplain #LINEAR linear} or {@linkplain #CANTOR_DIAGONAL Cantor-diagonal}
131         * scanning, spiral scanning can be extended to grids of three or more dimensions by repeating the
132         * scan pattern in consecutive planes. Spiral scanning is continuous in any one plane, but continuity
133         * in grids of more than two dimensions can only be maintained by reversing the inward/outward direction
134         * of the scan in alternate planes.
135         *
136         * <center><img src="doc-files/SpiralScanning.png"></center>
137         */
138        @UML(identifier="Spiral scanning", obligation=CONDITIONAL, specification=ISO_19123)
139        public static final SequenceType SPIRAL = new SequenceType("SPIRAL");
140    
141        /**
142         * Ordering based on a space-filling curve generated by progressively subdividing a space into quadrants
143         * and ordering the quadrants in a Z pattern. The ordering index for each grid point is computed by converting
144         * the grid coordinates to binary numbers and interleaving the bits of the resulting values. Given the list
145         * of the grid axes specified by {@linkplain SequenceRule#getScanDirection scan direction}, the bits of the
146         * coordinate corresponding to an axis are less significant than those of the coordinate corresponding to the
147         * next axis in the list. Morton ordering can be extended to any number of dimensions. Morton ordering is
148         * discontinuous.
149         * <p>
150         * <b>NOTE:</b> Because of the shape of the curve formed by the initial ordering of quadrants,
151         * Morton ordering is also known as Z ordering.
152         * <p>
153         * <center><img src="doc-files/Morton.png"></center>
154         * <p>
155         * A grid generated with the Morton ordering technique will be square and its size in each direction
156         * will be a multiple of a power of 2. However, the bit interleaving technique for generating an index
157         * can be used to order the grid points in any grid, including grids that are irregular in shape or have
158         * grid cells of different sizes.
159         */
160        @UML(identifier="Morton order", obligation=CONDITIONAL, specification=ISO_19123)
161        public static final SequenceType MORTON = new SequenceType("MORTON");
162    
163        /**
164         * Ordering based on a space-filling curve generated by progressively subdividing a space into quadrants.
165         * This is similar to {@linkplain #MORTON Morton} scanning, but the initial pattern of subdivision is different
166         * for Hilbert curves. Further subdivision involves replacement of parts of the curve by different patterns,
167         * unlike the simple replication of a single pattern as in Morton ordering. There are two sets of patterns.
168         * The left-hand column of the figure includes those for which the sense of the scan directions is the same
169         * - both are positive or both negative. The right-hand column of the figure includes those for which the
170         * sense of the scan directions is opposite - one is positive and one is negative. A Hilbert curve can only
171         * be constructed with patterns from the same set; it uses all the patterns in that set.
172         * <p>
173         * <b>NOTE:</b> Because of the shape of the curve formed by the initial ordering of quadrants, Hilbert
174         * ordering is also known as pi ordering.
175         *
176         * <center><img src="doc-files/Hilbert.png"></center>
177         */
178        @UML(identifier="Hilbert order", obligation=CONDITIONAL, specification=ISO_19123)
179        public static final SequenceType HILBERT = new SequenceType("HILBERT");
180    
181        /**
182         * Constructs an element of the given name. The new element is
183         * automatically added to the list returned by {@link #values()}.
184         *
185         * @param name The name of the new element.
186         *        This name must not be in use by an other element of this type.
187         */
188        private SequenceType(final String name) {
189            super(name, VALUES);
190        }
191    
192        /**
193         * Returns the list of {@code SequenceType}s.
194         *
195         * @return The list of codes declared in the current JVM.
196         */
197        public static SequenceType[] values() {
198            synchronized (VALUES) {
199                return VALUES.toArray(new SequenceType[VALUES.size()]);
200            }
201        }
202    
203        /**
204         * Returns the list of codes of the same kind than this code list element.
205         * Invoking this method is equivalent to invoking {@link #values()}, except that
206         * this method can be invoked on an instance of the parent {@code CodeList} class.
207         */
208        @Override
209        public SequenceType[] family() {
210            return values();
211        }
212    
213        /**
214         * Returns the sequence type that matches the given string, or returns a
215         * new one if none match it. More specifically, this methods returns the first instance for
216         * which <code>{@linkplain #name() name()}.{@linkplain String#equals equals}(code)</code>
217         * returns {@code true}. If no existing instance is found, then a new one is created for
218         * the given name.
219         *
220         * @param code The name of the code to fetch or to create.
221         * @return A code matching the given name.
222         */
223        public static SequenceType valueOf(String code) {
224            return valueOf(SequenceType.class, code);
225        }
226    }