Interface CoordinateSequence

  1 /*
  2  * Copyright (c) 2018 Vivid Solutions
  3  *
  4  * All rights reserved. This program and the accompanying materials
  5  * are made available under the terms of the Eclipse Public License 2.0
  6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  8  * and the Eclipse Distribution License is available at
  9  *
 10  * http://www.eclipse.org/org/documents/edl-v10.php.
 11  */
 12 package org.locationtech.jts.geom;
 13  
 14 import org.locationtech.jts.geom.impl.CoordinateArraySequenceFactory;
 15 import org.locationtech.jts.geom.impl.PackedCoordinateSequenceFactory;
 16  
 17 /**
 18  * The internal representation of a list of coordinates inside a Geometry.
 19  * <p>
 20  * This allows Geometries to store their
 21  * points using something other than the JTS {@link Coordinate} class. 
 22  * For example, a storage-efficient implementation
 23  * might store coordinate sequences as an array of x's
 24  * and an array of y's. 
 25  * Or a custom coordinate class might support extra attributes like M-values.
 26  * <p>
 27  * Implementing a custom coordinate storage structure
 28  * requires implementing the {@link CoordinateSequence} and
 29  * {@link CoordinateSequenceFactory} interfaces. 
 30  * To use the custom CoordinateSequence, create a
 31  * new {@link GeometryFactory} parameterized by the CoordinateSequenceFactory
 32  * The {@link GeometryFactory} can then be used to create new {@link Geometry}s.
 33  * The new Geometries
 34  * will use the custom CoordinateSequence implementation.
 35  * <p>
 36  * For an example, see the code for
 37  * {@link ExtendedCoordinateExample}.
 38  *
 39  * @see CoordinateArraySequenceFactory
 40  * @see PackedCoordinateSequenceFactory
 41  * @see ExtendedCoordinateExample
 42  *
 43  * @version 1.7
 44  */
 45 public interface CoordinateSequence
 46     extends Cloneable
 47 {
 48   /** Standard ordinate index value for, where X is 0 */
 49   int X = 0;
 50  
 51   /** Standard ordinate index value for, where Y is 1 */
 52   int Y = 1;
 53   
 54   /**
 55    * Standard ordinate index value for, where Z is 2.
 56    *
 57    * <p>This constant assumes XYZM coordinate sequence definition, please check this assumption
 58    * using {@link #getDimension()} and {@link #getMeasures()} before use.
 59    */
 60   /** Standard z-ordinate index */
 61   int Z = 2;
 62  
 63   /**
 64    * Standard ordinate index value for, where M is 3.
 65    *
 66    * <p>This constant assumes XYZM coordinate sequence definition, please check this assumption
 67    * using {@link #getDimension()} and {@link #getMeasures()} before use.
 68    */
 69   int M = 3;
 70  
 71   /**
 72    * Returns the dimension (number of ordinates in each coordinate) for this sequence.
 73    *
 74    * <p>This total includes any measures, indicated by non-zero {@link #getMeasures()}.
 75    *
 76    * @return the dimension of the sequence.
 77    */
 78   int getDimension();
 79  
 80   /**
 81    * Returns the number of measures included in {@link #getDimension()} for each coordinate for this
 82    * sequence.
 83    * 
 84    * For a measured coordinate sequence a non-zero value is returned.
 85    * <ul>
 86    * <li>For XY sequence measures is zero</li>
 87    * <li>For XYM sequence measure is one<li>
 88    * <li>For XYZ sequence measure is zero</li>
 89    * <li>For XYZM sequence measure is one</li>
 90    * <li>Values greater than one are supported</li>
 91    * </ul>
 92    *
 93    * @return the number of measures included in dimension
 94    */
 95   default int getMeasures() {
 96     return 0;
 97   }
 98   
 99   /**
100    * Checks {@link #getDimension()} and {@link #getMeasures()} to determine if {@link #getZ(int)}
101    * is supported.
102    * 
103    * @return true if {@link #getZ(int)} is supported.
104    */
105   default boolean hasZ() {
106       return (getDimension()-getMeasures()) > 2;
107   }
108  
109   /**
110    * Tests whether the coordinates in the sequence have measures associated with them. Returns true
111    * if {@link #getMeasures()} > 0. See {@link #getMeasures()} to determine the number of measures
112    * present.
113    *
114    * @return true if {@link #getM(int)} is supported.
115    *
116    * @see #getMeasures()
117    * @see #getM(int)
118    */
119   default boolean hasM() {
120       return getMeasures() > 0;
121   }
122  
123   /**
124    * Creates a coordinate for use in this sequence.
125    * <p>
126    * The coordinate is created supporting the same number of {@link #getDimension()} and {@link #getMeasures()}
127    * as this sequence and is suitable for use with {@link #getCoordinate(int, Coordinate)}.
128    * </p>
129    * @return coordinate for use with this sequence
130    */
131   default Coordinate createCoordinate() {
132     return Coordinates.create(getDimension(), getMeasures());
133   }
134   
135   /**
136    * Returns (possibly a copy of) the i'th coordinate in this sequence.
137    * Whether or not the Coordinate returned is the actual underlying
138    * Coordinate or merely a copy depends on the implementation.
139    * <p>
140    * Note that in the future the semantics of this method may change
141    * to guarantee that the Coordinate returned is always a copy.
142    * Callers should not to assume that they can modify a CoordinateSequence by
143    * modifying the object returned by this method.
144    *
145    * @param i the index of the coordinate to retrieve
146    * @return the i'th coordinate in the sequence
147    */
148   Coordinate getCoordinate(int i);
149  
150   /**
151    * Returns a copy of the i'th coordinate in this sequence.
152    * This method optimizes the situation where the caller is
153    * going to make a copy anyway - if the implementation
154    * has already created a new Coordinate object, no further copy is needed.
155    *
156    * @param i the index of the coordinate to retrieve
157    * @return a copy of the i'th coordinate in the sequence
158    */
159   Coordinate getCoordinateCopy(int i);
160  
161   /**
162    * Copies the i'th coordinate in the sequence to the supplied
163    * {@link Coordinate}.  Only the first two dimensions are copied.
164    *
165    * @param index the index of the coordinate to copy
166    * @param coord a {@link Coordinate} to receive the value
167    */
168   void getCoordinate(int index, Coordinate coord);
169  
170   /**
171    * Returns ordinate X (0) of the specified coordinate.
172    *
173    * @param index
174    * @return the value of the X ordinate in the index'th coordinate
175    */
176   double getX(int index);
177  
178   /**
179    * Returns ordinate Y (1) of the specified coordinate.
180    *
181    * @param index
182    * @return the value of the Y ordinate in the index'th coordinate
183    */
184   double getY(int index);
185  
186   /**
187    * Returns ordinate Z of the specified coordinate if available.
188    * 
189    * @param index
190    * @return the value of the Z ordinate in the index'th coordinate, or Double.NaN if not defined.
191    */
192   default double getZ(int index)
193   {
194     if (hasZ()) {
195         return getOrdinate(index, 2);
196     } else {
197         return Double.NaN;
198     }
199   }
200  
201   /**
202    * Returns ordinate M of the specified coordinate if available.
203    * 
204    * @param index
205    * @return the value of the M ordinate in the index'th coordinate, or Double.NaN if not defined.
206    */
207   default double getM(int index)
208   {
209     if (hasM()) {
210       final int mIndex = getDimension()-getMeasures();
211       return getOrdinate( index, mIndex );
212     }
213     else {
214         return Double.NaN;
215     }
216   }
217   
218   /**
219    * Returns the ordinate of a coordinate in this sequence.
220    * Ordinate indices 0 and 1 are assumed to be X and Y.
221    * <p>
222    * Ordinates indices greater than 1 have user-defined semantics
223    * (for instance, they may contain other dimensions or measure
224    * values as described by {@link #getDimension()} and {@link #getMeasures()}).
225    *
226    * @param index  the coordinate index in the sequence
227    * @param ordinateIndex the ordinate index in the coordinate (in range [0, dimension-1])
228    */
229   double getOrdinate(int index, int ordinateIndex);
230  
231   /**
232    * Returns the number of coordinates in this sequence.
233    * @return the size of the sequence
234    */
235   int size();
236  
237   /**
238    * Sets the value for a given ordinate of a coordinate in this sequence.
239    *
240    * @param index  the coordinate index in the sequence
241    * @param ordinateIndex the ordinate index in the coordinate (in range [0, dimension-1])
242    * @param value  the new ordinate value
243    */
244   void setOrdinate(int index, int ordinateIndex, double value);
245  
246   /**
247    * Returns (possibly copies of) the Coordinates in this collection.
248    * Whether or not the Coordinates returned are the actual underlying
249    * Coordinates or merely copies depends on the implementation. Note that
250    * if this implementation does not store its data as an array of Coordinates,
251    * this method will incur a performance penalty because the array needs to
252    * be built from scratch.
253    *
254    * @return a array of coordinates containing the point values in this sequence
255    */
256   Coordinate[] toCoordinateArray();
257  
258   /**
259    * Expands the given {@link Envelope} to include the coordinates in the sequence.
260    * Allows implementing classes to optimize access to coordinate values.
261    *
262    * @param env the envelope to expand
263    * @return a ref to the expanded envelope
264    */
265   Envelope expandEnvelope(Envelope env);
266  
267   /**
268    * Returns a deep copy of this collection.
269    * Called by Geometry#clone.
270    *
271    * @return a copy of the coordinate sequence containing copies of all points
272    * @deprecated Recommend {@link #copy()} 
273    */
274   Object clone();
275   
276   /**
277    * Returns a deep copy of this collection.
278    *
279    * @return a copy of the coordinate sequence containing copies of all points
280    */
281   CoordinateSequence copy();
282 }
283