/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2014 - 2015, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.geometry.jts; import com.vividsolutions.jts.geom.CoordinateSequence; import com.vividsolutions.jts.geom.GeometryFactory; /** * Simple support class that allows accumulating doubles in an array, transparently growing it as * the data gets added. * * @author Andrea Aime - GeoSolutions * */ class GrowableOrdinateArray { private double[] data; private int curr; /** * Creates an array of the given initial size * * @param size */ public GrowableOrdinateArray(int size) { this.data = new double[size]; } /** * Builds an initialized array, which will be primed when {@link #ensureLength(int)} is called */ GrowableOrdinateArray() { } /** * Appends a single number to the array * * @param d */ public void add(double d) { ensureLength(curr + 1); data[curr++] = d; } /** * Appends a two numbers to the array * * @param d */ public void add(double d1, double d2) { ensureLength(curr + 2); data[curr++] = d1; data[curr++] = d2; } /** * Appends a list of doubles to the array * * @param d */ public void addAll(double... d) { ensureLength(curr + d.length); System.arraycopy(d, 0, data, curr, d.length); curr += d.length; } /** * Appends a whole coordinate sequence to the array * * @param cs */ public void addAll(CoordinateSequence cs) { int coordinatesCount = cs.size(); ensureLength(curr + coordinatesCount * 2); for (int i = 0; i < coordinatesCount; i++) { data[curr + i * 2] = cs.getOrdinate(i, 0); data[curr + i * 2 + 1] = cs.getOrdinate(i, 1); } curr += coordinatesCount * 2; } /** * Returns the accumulated numbers, in an array cut to the current size * * @return */ public double[] getData() { if (data == null) { return new double[0]; } if (data.length == curr) { return data; } else { double[] result = new double[curr]; System.arraycopy(data, 0, result, 0, curr); return result; } } /** * Returns the current data array, raw, uncut * @return */ public double[] getDataRaw() { return data; } /** * Turns the array of ordinates into a coordinate sequence * * @param gf * @return */ public CoordinateSequence toCoordinateSequence(GeometryFactory gf) { double[] data = getData(); CoordinateSequence cs = gf.getCoordinateSequenceFactory().create(data.length / 2, 2); for (int i = 0; i < cs.size(); i++) { cs.setOrdinate(i, 0, data[i * 2]); cs.setOrdinate(i, 1, data[i * 2 + 1]); } return cs; } public int size() { return curr; } public void setSize(int newSize) { if (newSize < 0) { throw new IllegalArgumentException("The size must zero or positive, it was " + newSize + " instead"); } ensureLength(newSize); curr = newSize; } /** * Ensures the data array has the specified lenght, or grows it otherwise * * @param length */ void ensureLength(int length) { if (data == null) { data = new double[length]; } else { int currLength = data.length; if (length > currLength) { int newLength = (currLength * 3) / 2 + 1; if (newLength < length) { newLength = length; } double[] newData = new double[newLength]; System.arraycopy(data, 0, newData, 0, currLength); this.data = newData; } } } /** * Reverses the values between start and end assuming it's a packed array of x/y ordinates * * @param start * @param size */ public void reverseOrdinates(int start, int end) { int limit = (start + end) / 2; for (int i = start; i < limit; i += 2) { // x double tmp = data[i]; int simmetric = end - (i - start) - 1; data[i] = data[simmetric]; data[simmetric] = tmp; // y tmp = data[i + 1]; simmetric = end - (i - start); data[i + 1] = data[simmetric]; data[simmetric] = tmp; } } @Override public String toString() { StringBuilder sb = new StringBuilder("GrowableDataArray(" + curr + ")["); for (int i = 0; i < curr; i++) { sb.append(data[i]); if (i < curr - 1) { sb.append(", "); } } sb.append("]"); return sb.toString(); } /** * Closes the sequence by adding the last point as first */ public void close() { add(data[0], data[1]); } /** * Copies a sub-array from another growable array * * @param other * @param from * @param to */ public void copy(GrowableOrdinateArray other, int from, int to) { ensureLength(to + 1); System.arraycopy(other.data, 0, data, 0, to + 1); this.curr = to + 1; } }