Class CoordinateArraySequence

  1 /*
  2  * Copyright (c) 2016 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.impl;
 13  
 14 import java.io.Serializable;
 15 import java.lang.reflect.Array;
 16  
 17 import org.locationtech.jts.geom.*;
 18  
 19 /**
 20  * A {@link CoordinateSequence} backed by an array of {@link Coordinate}s.
 21  * This is the implementation that {@link Geometry}s use by default.
 22  * Coordinates returned by #toArray and #getCoordinate are live --
 23  * modifications to them are actually changing the
 24  * CoordinateSequence's underlying data.
 25  * A dimension may be specified for the coordinates in the sequence,
 26  * which may be 2 or 3.
 27  * The actual coordinates will always have 3 ordinates,
 28  * but the dimension is useful as metadata in some situations. 
 29  *
 30  * @version 1.7
 31  */
 32 public class CoordinateArraySequence
 33     implements CoordinateSequence, Serializable
 34 {
 35   //With contributions from Markus Schaber [schabios@logi-track.com] 2004-03-26
 36   private static final long serialVersionUID = -915438501601840650L;
 37  
 38   /**
 39    * The actual dimension of the coordinates in the sequence.
 40    * Allowable values are 2, 3 or 4.
 41    */
 42   private int dimension = 3;
 43   /**
 44    * The number of measures of the coordinates in the sequence.
 45    * Allowable values are 0 or 1.
 46    */
 47   private int measures = 0;
 48   
 49   private Coordinate[] coordinates;
 50  
 51   /**
 52    * Constructs a sequence based on the given array
 53    * of {@link Coordinate}s (the
 54    * array is not copied).
 55    * The coordinate dimension defaults to 3.
 56    *
 57    * @param coordinates the coordinate array that will be referenced.
 58    */
 59   public CoordinateArraySequence(Coordinate[] coordinates)
 60   {
 61     this(coordinates, CoordinateArrays.dimension(coordinates), CoordinateArrays.measures(coordinates));
 62   }
 63  
 64   /**
 65    * Constructs a sequence based on the given array 
 66    * of {@link Coordinate}s (the
 67    * array is not copied).
 68    *
 69    * @param coordinates the coordinate array that will be referenced.
 70    * @param dimension the dimension of the coordinates
 71    */
 72   public CoordinateArraySequence(Coordinate[] coordinates, int dimension) {
 73     this(coordinates, dimension, CoordinateArrays.measures(coordinates));    
 74   }
 75   
 76   /**
 77    * Constructs a sequence based on the given array 
 78    * of {@link Coordinate}s (the array is not copied).
 79    * <p>
 80    * It is your responsibility to ensure the array contains Coordinates of the
 81    * indicated dimension and measures (See 
 82    * {@link CoordinateArrays#enforceConsistency(Coordinate[])} ).</p>
 83    *
 84    * @param coordinates the coordinate array that will be referenced.
 85    * @param dimension the dimension of the coordinates
 86    */
 87   public CoordinateArraySequence(Coordinate[] coordinates, int dimension, int measures)
 88   {
 89     this.dimension = dimension;
 90     this.measures = measures;
 91     if (coordinates == null) {
 92       this.coordinates = new Coordinate[0];
 93     }
 94     else {
 95       this.coordinates = coordinates;
 96     }
 97   }
 98  
 99   /**
100    * Constructs a sequence of a given size, populated
101    * with new {@link Coordinate}s.
102    *
103    * @param size the size of the sequence to create
104    */
105   public CoordinateArraySequence(int size) {
106     coordinates = new Coordinate[size];
107     for (int i = 0; i < size; i++) {
108       coordinates[i] = new Coordinate();
109     }
110   }
111  
112   /**
113    * Constructs a sequence of a given size, populated
114    * with new {@link Coordinate}s.
115    *
116    * @param size the size of the sequence to create
117    * @param dimension the dimension of the coordinates
118    */
119   public CoordinateArraySequence(int size, int dimension) {
120     coordinates = new Coordinate[size];
121     this.dimension = dimension;
122     for (int i = 0; i < size; i++) {
123       coordinates[i] = Coordinates.create(dimension);
124     }
125   }
126   /**
127    * Constructs a sequence of a given size, populated
128    * with new {@link Coordinate}s.
129    *
130    * @param size the size of the sequence to create
131    * @param dimension the dimension of the coordinates
132    */
133   public CoordinateArraySequence(int size, int dimension,int measures) {
134     coordinates = new Coordinate[size];
135     this.dimension = dimension;
136     this.measures = measures;
137     for (int i = 0; i < size; i++) {
138       coordinates[i] = createCoordinate();
139     }
140   }
141  
142   /**
143    * Creates a new sequence based on a deep copy of the given {@link CoordinateSequence}.
144    * The coordinate dimension is set to equal the dimension of the input.
145    *
146    * @param coordSeq the coordinate sequence that will be copied.
147    */
148   public CoordinateArraySequence(CoordinateSequence coordSeq)
149   {
150     // NOTE: this will make a sequence of the default dimension
151     if (coordSeq == null) {
152       coordinates = new Coordinate[0];
153       return;
154     }
155     dimension = coordSeq.getDimension();
156     measures = coordSeq.getMeasures();    
157     coordinates = new Coordinate[coordSeq.size()];
158  
159     for (int i = 0; i < coordinates.length; i++) {
160       coordinates[i] = coordSeq.getCoordinateCopy(i);
161     }
162   }
163  
164   /**
165    * @see org.locationtech.jts.geom.CoordinateSequence#getDimension()
166    */
167   public int getDimension()
168   {
169     return dimension;
170   }
171   
172   @Override
173   public int getMeasures()
174   {
175     return measures;
176   }
177  
178   /**
179    * Get the Coordinate with index i.
180    *
181    * @param i
182    *                  the index of the coordinate
183    * @return the requested Coordinate instance
184    */
185   public Coordinate getCoordinate(int i) {
186     return coordinates[i];
187   }
188  
189   /**
190    * Get a copy of the Coordinate with index i.
191    *
192    * @param i  the index of the coordinate
193    * @return a copy of the requested Coordinate
194    */
195   public Coordinate getCoordinateCopy(int i) {
196     Coordinate copy = createCoordinate();
197     copy.setCoordinate(coordinates[i]);
198     return copy;
199   }
200  
201   /**
202    * @see org.locationtech.jts.geom.CoordinateSequence#getX(int)
203    */
204   public void getCoordinate(int index, Coordinate coord) {
205     coord.setCoordinate(coordinates[index]);
206   }
207  
208   /**
209    * @see org.locationtech.jts.geom.CoordinateSequence#getX(int)
210    */
211   public double getX(int index) {
212     return coordinates[index].x;
213   }
214  
215   /**
216    * @see org.locationtech.jts.geom.CoordinateSequence#getY(int)
217    */
218   public double getY(int index) {
219     return coordinates[index].y;
220   }
221  
222   /**
223    * @see org.locationtech.jts.geom.CoordinateSequence#getZ(int)
224    */
225   public double getZ(int index)
226   {
227     if (hasZ()) {
228       return coordinates[index].getZ();
229     } else {
230       return Double.NaN;
231     }
232  
233   }
234   
235   /**
236    * @see org.locationtech.jts.geom.CoordinateSequence#getM(int)
237    */
238   public double getM(int index) {
239     if (hasM()) {
240       return coordinates[index].getM();
241     }
242     else {
243         return Double.NaN;
244     }    
245   }
246   
247   /**
248    * @see org.locationtech.jts.geom.CoordinateSequence#getOrdinate(int, int)
249    */
250   public double getOrdinate(int index, int ordinateIndex)
251   {
252     switch (ordinateIndex) {
253       case CoordinateSequence.X:  return coordinates[index].x;
254       case CoordinateSequence.Y:  return coordinates[index].y;
255       default:
256           return coordinates[index].getOrdinate(ordinateIndex);
257     }
258   }
259  
260   /**
261    * Creates a deep copy of the Object
262    *
263    * @return The deep copy
264    * @deprecated
265    */
266   public Object clone() {
267     return copy();
268   }
269   /**
270    * Creates a deep copy of the CoordinateArraySequence
271    *
272    * @return The deep copy
273    */
274   public CoordinateArraySequence copy() {
275     Coordinate[] cloneCoordinates = new Coordinate[size()];
276     for (int i = 0; i < coordinates.length; i++) {
277       Coordinate duplicate = createCoordinate();
278       duplicate.setCoordinate(coordinates[i]);
279       cloneCoordinates[i] = duplicate;
280     }
281     return new CoordinateArraySequence(cloneCoordinates, dimension, measures);
282   }
283   /**
284    * Returns the size of the coordinate sequence
285    *
286    * @return the number of coordinates
287    */
288   public int size() {
289     return coordinates.length;
290   }
291  
292   /**
293    * @see org.locationtech.jts.geom.CoordinateSequence#setOrdinate(int, int, double)
294    */
295   public void setOrdinate(int index, int ordinateIndex, double value)
296   {
297     switch (ordinateIndex) {
298       case CoordinateSequence.X:
299         coordinates[index].x = value;
300         break;
301       case CoordinateSequence.Y:
302         coordinates[index].y = value;
303         break;
304       default:
305         coordinates[index].setOrdinate(ordinateIndex, value);
306     }
307   }
308  
309   /**
310    * This method exposes the internal Array of Coordinate Objects
311    *
312    * @return the Coordinate[] array.
313    */
314   public Coordinate[] toCoordinateArray() {
315     return coordinates;
316   }
317  
318   public Envelope expandEnvelope(Envelope env)
319   {
320     for (int i = 0; i < coordinates.length; i++ ) {
321       env.expandToInclude(coordinates[i]);
322     }
323     return env;
324   }
325  
326   /**
327    * Returns the string Representation of the coordinate array
328    *
329    * @return The string
330    */
331   public String toString() {
332     if (coordinates.length > 0) {
333       StringBuilder strBuilder = new StringBuilder(17 * coordinates.length);
334       strBuilder.append('(');
335       strBuilder.append(coordinates[0]);
336       for (int i = 1; i < coordinates.length; i++) {
337         strBuilder.append(", ");
338         strBuilder.append(coordinates[i]);
339       }
340       strBuilder.append(')');
341       return strBuilder.toString();
342     } else {
343       return "()";
344     }
345   }
346 }
347