001    /*
002     *    GeoAPI - Java interfaces for OGC/ISO standards
003     *    http://www.geoapi.org
004     *
005     *    Copyright (C) 2004-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.geometry;
033    
034    import org.opengis.geometry.coordinate.Position;
035    import org.opengis.referencing.crs.CoordinateReferenceSystem;
036    import org.opengis.annotation.UML;
037    import org.opengis.annotation.Classifier;
038    import org.opengis.annotation.Stereotype;
039    
040    import static org.opengis.annotation.Obligation.*;
041    import static org.opengis.annotation.Specification.*;
042    
043    
044    /**
045     * Holds the coordinates for a position within some coordinate reference system. Since
046     * {@code DirectPosition}s, as data types, will often be included in larger objects (such as
047     * {@linkplain org.opengis.geometry.Geometry geometries}) that have references to
048     * {@linkplain CoordinateReferenceSystem coordinate reference system}, the
049     * {@link #getCoordinateReferenceSystem} method may returns {@code null} if this particular
050     * {@code DirectPosition} is included in a larger object with such a reference to a
051     * {@linkplain CoordinateReferenceSystem coordinate reference system}. In this case,
052     * the coordinate reference system is implicitly assumed to take on the value of the containing
053     * object's {@linkplain CoordinateReferenceSystem coordinate reference system}.
054     *
055     * @departure easeOfUse
056     *   The ISO specification defines this interface in the <code>coordinate</code> sub-package.
057     *   GeoAPI moved this interface into the <code>org.opengis.geometry</code> root package for
058     *   convenience, because it is extensively used.
059     *
060     * @author  Martin Desruisseaux (IRD)
061     * @version 3.1
062     * @since   1.0
063     *
064     * @navassoc 1 - - CoordinateReferenceSystem
065     */
066    @Classifier(Stereotype.DATATYPE)
067    @UML(identifier="DirectPosition", specification=ISO_19107)
068    public interface DirectPosition extends Position {
069        /**
070         * The coordinate reference system in which the coordinate is given. May be {@code null} if this
071         * particular {@code DirectPosition} is included in a larger object with such a reference to a
072         * {@linkplain CoordinateReferenceSystem coordinate reference system}. In this case, the
073         * coordinate reference system is implicitly assumed to take on the value of the containing
074         * object's {@linkplain CoordinateReferenceSystem coordinate reference system}.
075         *
076         * @return The coordinate reference system, or {@code null}.
077         */
078        @UML(identifier="coordinateReferenceSystem", obligation=MANDATORY, specification=ISO_19107)
079        CoordinateReferenceSystem getCoordinateReferenceSystem();
080    
081        /**
082         * The length of coordinate sequence (the number of entries). This is determined by the
083         * {@linkplain #getCoordinateReferenceSystem() coordinate reference system}.
084         *
085         * @return The dimensionality of this position.
086         */
087        @UML(identifier="dimension", obligation=MANDATORY, specification=ISO_19107)
088        int getDimension();
089    
090        /**
091         * A <b>copy</b> of the ordinates presented as an array of double values.
092         * Please note that this is only a copy (the real values may be stored in
093         * another format) so changes to the returned array will not affect the
094         * source DirectPosition.
095         *
096         * <blockquote><pre>
097         * final int dim = position.{@linkplain #getDimension getDimension}();
098         * for (int i=0; i&lt;dim; i++) {
099         *     position.{@linkplain #getOrdinate getOrdinate}(i); // no copy overhead
100         * }
101         * </pre></blockquote>
102         *
103         * To manipulate ordinates, the following idiom can be used:
104         *
105         * <blockquote><pre>
106         * position.{@linkplain #setOrdinate setOrdinate}(i, value); // edit in place
107         * </pre></blockquote>
108         *
109         * There are a couple reasons for requesting a copy:
110         *
111         * <ul>
112         *   <li>We want an array of coordinates with the intend to modify it for computation purpose
113         *       (without modifying the original {@code DirectPosition}), or we want to protect the
114         *       array from future {@code DirectPosition} changes.</li>
115         *   <li>If {@code DirectPosition.getOrdinates()} is guaranteed to not return the backing array,
116         *       then we can work directly on this array. If we don't have this guarantee, then we must
117         *       conservatively clone the array in every cases.</li>
118         *   <li>Cloning the returned array is useless if the implementation cloned the array or was
119         *       forced to returns a new array anyway (for example because the coordinates were
120         *       computed on the fly)</li>
121         * </ul>
122         *
123         * Precedence is given to data integrity over {@code getOrdinates()} performance.
124         * Performance concern can be avoided with usage of {@link #getOrdinate(int)}.
125         *
126         * @return A copy of the coordinates. Changes in the returned array will not be reflected back
127         *         in this {@code DirectPosition} object.
128         */
129        @UML(identifier="coordinate", obligation=MANDATORY, specification=ISO_19107)
130        double[] getCoordinate();
131    
132        /**
133         * Returns the ordinate at the specified dimension.
134         *
135         * @param dimension The dimension in the range 0 to {@linkplain #getDimension dimension}-1.
136         * @return The coordinate at the specified dimension.
137         * @throws IndexOutOfBoundsException If the given index is negative or is equals or greater
138         *         than the {@linkplain #getDimension() position dimension}.
139         */
140        double getOrdinate(int dimension) throws IndexOutOfBoundsException;
141    
142        /**
143         * Sets the ordinate value along the specified dimension.
144         *
145         * @param dimension the dimension for the ordinate of interest.
146         * @param value the ordinate value of interest.
147         * @throws IndexOutOfBoundsException If the given index is negative or is equals or greater
148         *         than the {@linkplain #getDimension() position dimension}.
149         * @throws UnsupportedOperationException if this direct position is immutable.
150         */
151        void setOrdinate(int dimension, double value)
152                throws IndexOutOfBoundsException, UnsupportedOperationException;
153    
154        /**
155         * Compares this direct position with the specified object for equality.
156         * Two direct positions are considered equal if the following conditions
157         * are meet:
158         *
159         * <ul>
160         *   <li>{@code object} is non-null and is an instance of {@code DirectPosition}.</li>
161         *   <li>Both direct positions have the same {@linkplain #getDimension() number of dimensions}.</li>
162         *   <li>Both direct positions have the same or equal {@linkplain #getCoordinateReferenceSystem
163         *       coordinate reference system}.</li>
164         *   <li>For all dimension <var>i</var>, the {@linkplain #getOrdinate ordinate value} of both
165         *       direct positions at that dimension are equals in the sense of {@link Double#equals(Object)}.
166         *       In other words, <code>{@linkplain java.util.Arrays#equals(double[],double[])
167         *       Arrays.equals}({@linkplain #getCoordinate()}, object.getCoordinate())</code>
168         *       returns {@code true}.</li>
169         * </ul>
170         *
171         * @param object The object to compare with this direct position for equality.
172         * @return {@code true} if the given object is equals to this direct position.
173         *
174         * @since 2.1
175         */
176        @Override
177        boolean equals(Object object);
178    
179        /**
180         * Returns a hash code value for this direct position. This method should returns
181         * the same value as:
182         *
183         * <code>{@linkplain java.util.Arrays#hashCode(double[]) Arrays.hashCode}({@linkplain
184         * #getCoordinate()}) + {@linkplain #getCoordinateReferenceSystem()}.hashCode()</code>
185         *
186         * where the right hand side of the addition is omitted if the coordinate reference
187         * system is null.
188         *
189         * @return A hash code value for this direct position.
190         *
191         * @since 2.1
192         */
193        @Override
194        int hashCode();
195    }