/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2004-2008, 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.geotoolkit.geometry.jts.coordinatesequence; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.impl.PackedCoordinateSequence; /** * @todo class description * * @author jeichar * @module * @since 2.1.x */ public class LiteCoordinateSequence extends PackedCoordinateSequence { /** * The packed coordinate array */ private double[] coords; /** * Cached size, getSize() gets called an incredible number of times during rendering * (a profile shows 2 million calls when rendering 90.000 linear features) */ private int size; /** * Builds a new packed coordinate sequence * * @param coords * */ public LiteCoordinateSequence(final double[] coords) { this.dimension = 2; if (coords.length % dimension != 0) { throw new IllegalArgumentException("Packed array does not contain " + "an integral number of coordinates"); } this.coords = coords; this.size = coords.length / dimension; } /** * Builds a new packed coordinate sequence out of a float coordinate array * * @param coordinates */ public LiteCoordinateSequence(final float[] coordinates) { this.coords = new double[coordinates.length]; this.dimension = 2; this.size = coords.length / dimension; System.arraycopy(coordinates, 0, this.coords, 0, coordinates.length); } /** * Builds a new packed coordinate sequence out of a coordinate array * * @param coordinates */ public LiteCoordinateSequence(Coordinate[] coordinates) { if (coordinates == null) { coordinates = new Coordinate[0]; } this.dimension = 2; this.coords = new double[coordinates.length * this.dimension]; for (int i = 0; i < coordinates.length; i++) { coords[i * this.dimension] = coordinates[i].x; coords[i * this.dimension + 1] = coordinates[i].y; } this.size = coordinates.length; } /** * Builds a new empty packed coordinate sequence of a given size and dimension * * @param size * @param dimension * */ public LiteCoordinateSequence(final int size, final int dimension) { if (dimension != 2) { throw new IllegalArgumentException("This type of sequence is always 2 dimensional"); } this.dimension = 2; this.coords = new double[size * this.dimension]; this.size = coords.length / dimension; } /** * Copy constructor * @param seq */ public LiteCoordinateSequence(final LiteCoordinateSequence seq) { // a trivial benchmark can show that cloning arrays like this is actually faster // than calling clone on the array. this.dimension = seq.dimension; this.size = seq.size; final double[] orig = seq.getArray(); this.coords = new double[orig.length]; System.arraycopy(orig, 0, coords, 0, coords.length); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int) */ @Override public Coordinate getCoordinateInternal(final int i) { final double x = coords[i * dimension]; final double y = coords[i * dimension + 1]; final double z = dimension == 2 ? java.lang.Double.NaN : coords[i * dimension + 2]; return new Coordinate(x, y, z); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#size() */ @Override public int size() { return size; } /** * {@inheritDoc } */ @Override public Object clone() { final double[] clone = new double[coords.length]; System.arraycopy(coords, 0, clone, 0, coords.length); return new LiteCoordinateSequence(clone); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int) * Beware, for performace reasons the ordinate index is not checked, if * it's over dimensions you may not get an exception but a meaningless * value. */ @Override public double getOrdinate(final int index, final int ordinate) { return coords[index * dimension + ordinate]; } /** * {@inheritDoc } */ @Override public double getX(final int index) { return coords[index * dimension]; } /** * {@inheritDoc } */ @Override public double getY(final int index) { return coords[index * dimension + 1]; } /** * {@inheritDoc } */ @Override public void setOrdinate(final int index, final int ordinate, final double value) { coordRef = null; coords[index * dimension + ordinate] = value; } /** * {@inheritDoc } */ @Override public Envelope expandEnvelope(final Envelope env) { double minx = coords[0]; double maxx = minx; double miny = coords[1]; double maxy = miny; for (int i = 0; i < coords.length; i += dimension) { final double x = coords[i]; final double y = coords[i + 1]; if (x < minx) { minx = x; } else if (x > maxx) { maxx = x; } if (y < miny) { miny = y; } else if (y > maxy) { maxy = y; } } env.expandToInclude(minx, miny); env.expandToInclude(maxx, maxy); return env; } public double[] getArray() { return coords; } /** * @param coords2 */ public void setArray(final double[] coords2) { coords = coords2; size = coords.length / dimension; coordRef = null; } /** * if this is a dimension=2 seq, then this is the same as getArray(). * If its >2 dims this will make a new array with dim=2 */ public double[] getXYArray() { if (dimension == 2){ //this is always true return coords; } // this should never run, but its here for the future... final int n = size(); final double[] result = new double[n * 2]; for (int t = 0; t < n; t++) { result[t * 2] = getOrdinate(t, 0); result[t * 2 + 1] = getOrdinate(t, 1); } return result; } }