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