All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotools.geometry.jts.LiteCoordinateSequence Maven / Gradle / Ivy

Go to download

The main module contains the GeoTools public interfaces that are used by other GeoTools modules (and GeoTools applications). Where possible we make use industry standard terms as provided by OGC and ISO standards. The formal GeoTools public api consists of gt-metadata, jts and the gt-main module. The main module contains the default implementations that are available provided to other GeoTools modules using our factory system. Factories are obtained from an appropriate FactoryFinder, giving applications a chance configure the factory used using the Factory Hints facilities. FilterFactory ff = CommonFactoryFinder.getFilterFactory(); Expression expr = ff.add( expression1, expression2 ); If you find yourself using implementation specific classes chances are you doing it wrong: Expression expr = new AddImpl( expression1, expressiom2 );

The newest version!
/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2004-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 java.util.ArrayList;
import java.util.List;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateSequence;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.LinearRing;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.impl.PackedCoordinateSequence;

/**
 * @TODO class description
 *
 * @author jeichar
 * @since 2.1.x
 */
public class LiteCoordinateSequence extends PackedCoordinateSequence implements Cloneable {

    private static final GeometryFactory geomFac =
            new GeometryFactory(new LiteCoordinateSequenceFactory());

    /** 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 */
    public LiteCoordinateSequence(double[] coords, int dimensions) {
        this(coords, dimensions, 0);
    }

    /** Builds a new packed coordinate sequence */
    public LiteCoordinateSequence(double[] coords, int dimensions, int measures) {
        super(dimensions, measures);
        init(coords, dimensions);
    }

    /** Private initializer, allows sharing code between constructors */
    void init(double[] coords, int dimensions) {
        this.dimension = dimensions;
        if (dimensions < 2)
            throw new IllegalArgumentException("Invalid dimensions, must be at least 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 / dimensions;
    }

    /** Builds a new packed coordinate sequence */
    public LiteCoordinateSequence(double... coords) {
        this(coords, 2, 0);
    }

    /** Builds a new packed coordinate sequence out of a float coordinate array */
    public LiteCoordinateSequence(float[] coordinates, int dimension) {
        super(dimension, 0);
        double[] dcoords = new double[coordinates.length];
        for (int i = 0; i < coordinates.length; i++) {
            dcoords[i] = coordinates[i];
        }
        init(dcoords, dimension);
    }

    /** Builds a new packed coordinate sequence out of a float coordinate array */
    public LiteCoordinateSequence(float[] coordinates) {
        this(coordinates, 2);
    }

    /** Builds a new packed coordinate sequence out of a coordinate array */
    public LiteCoordinateSequence(Coordinate[] coordinates) {
        super(guessDimension(coordinates == null ? new Coordinate[0] : coordinates), 0);
        if (coordinates == null) coordinates = new Coordinate[0];
        this.dimension = guessDimension(coordinates);

        coords = new double[coordinates.length * this.dimension];
        for (int i = 0; i < coordinates.length; i++) {
            coords[i * this.dimension] = coordinates[i].x;
            if (this.dimension > 2) {
                coords[i * this.dimension + 1] = coordinates[i].y;
                coords[i * this.dimension + 2] = coordinates[i].getZ();
            } else if (this.dimension > 1) {
                coords[i * this.dimension + 1] = coordinates[i].y;
            }
        }
        this.size = coordinates.length;
    }

    private static int guessDimension(Coordinate[] coordinates) {
        for (Coordinate c : coordinates) {
            if (!java.lang.Double.isNaN(c.getZ())) {
                return 3;
            }
        }

        return 2;
    }

    /** Builds a new empty packed coordinate sequence of a given size and dimension */
    public LiteCoordinateSequence(int size, int dimension) {
        this(size, dimension, 0);
    }

    /** Builds a new empty packed coordinate sequence of a given size and dimension */
    public LiteCoordinateSequence(int size, int dimension, int measures) {
        super(dimension, measures);
        coords = new double[size * this.dimension];
        this.size = coords.length / dimension;
    }

    /** Copy constructor */
    public LiteCoordinateSequence(LiteCoordinateSequence seq) {
        super(seq.getDimension(), seq.getMeasures());
        // 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;
        double[] orig = seq.getArray();
        this.coords = new double[orig.length];
        System.arraycopy(orig, 0, coords, 0, coords.length);
    }

    public LiteCoordinateSequence(CoordinateSequence cs, int dimension) {
        super(dimension, cs.getMeasures());
        this.size = cs.size();
        this.dimension = dimension;

        if (cs instanceof LiteCoordinateSequence) {
            double[] orig = ((LiteCoordinateSequence) cs).getOrdinateArray(dimension);
            this.coords = new double[orig.length];
            System.arraycopy(orig, 0, coords, 0, coords.length);
        } else {
            this.coords = new double[size * dimension];
            int minDimension = Math.min(dimension, cs.getDimension());
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < minDimension; j++) {
                    coords[i * dimension + j] = cs.getOrdinate(i, j);
                }
            }
        }
    }

    /** @see org.locationtech.jts.geom.CoordinateSequence#getCoordinate(int) */
    public Coordinate getCoordinateInternal(int i) {
        double x = coords[i * dimension];
        double y = coords[i * dimension + 1];
        double z = dimension == 2 ? java.lang.Double.NaN : coords[i * dimension + 2];
        return new Coordinate(x, y, z);
    }

    /** @see org.locationtech.jts.geom.CoordinateSequence#size() */
    public int size() {
        return size;
    }

    @SuppressWarnings("deprecation")
    public Object clone() {
        double[] clone = new double[coords.length];
        System.arraycopy(coords, 0, clone, 0, coords.length);
        return new LiteCoordinateSequence(clone, dimension);
    }

    @Override
    public PackedCoordinateSequence copy() {
        return (PackedCoordinateSequence) clone();
    }

    /**
     * @see org.locationtech.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.
     */
    public double getOrdinate(int index, int ordinate) {
        return coords[index * dimension + ordinate];
    }

    /** @see org.locationtech.jts.geom.CoordinateSequence#getX(int) */
    public double getX(int index) {
        return coords[index * dimension];
    }

    /** @see org.locationtech.jts.geom.CoordinateSequence#getY(int) */
    public double getY(int index) {
        return coords[index * dimension + 1];
    }

    /** @see org.locationtech.jts.geom.PackedCoordinateSequence#setOrdinate(int, int, double) */
    public void setOrdinate(int index, int ordinate, double value) {
        coordRef = null;
        coords[index * dimension + ordinate] = value;
    }

    public Envelope expandEnvelope(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) {
            double x = coords[i];
            if (x < minx) minx = x;
            else if (x > maxx) maxx = x;
            double y = coords[i + 1];
            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(double[] coords2) {
        init(coords2, dimension);
        coordRef = null;
    }

    public void setArray(double[] coords2, int dimension) {
        init(coords2, 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) {
            return coords;
        }
        // this should never run, but its here for the future...
        int n = size();
        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;
    }

    public double[] getOrdinateArray(int dimensions) {
        if (dimensions == this.dimension) {
            return coords;
        }

        int n = size();
        double[] result = new double[n * dimensions];
        int minDimensions = Math.min(dimensions, this.dimension);
        for (int t = 0; t < n; t++) {
            for (int d = 0; d < minDimensions; d++) {
                result[t * 2 + d] = getOrdinate(t, d);
            }
        }
        return result;
    }

    /**
     * Clones the specified geometry using {@link LiteCoordinateSequence} in the result, with the
     * specified number of dimensions
     */
    public static Geometry cloneGeometry(Geometry geom, int dimension) {
        if (dimension < 2) {
            throw new IllegalArgumentException("Invalid dimension value, must be >= 2");
        }

        if (geom == null) return null;

        if (geom instanceof LineString) {
            return cloneGeometry((LineString) geom, dimension);
        } else if (geom instanceof Polygon) {
            return cloneGeometry((Polygon) geom, dimension);
        } else if (geom instanceof Point) {
            return cloneGeometry((Point) geom, dimension);
        } else {
            return cloneGeometry((GeometryCollection) geom, dimension);
        }
    }

    /** Clones the specified geometry using {@link LiteCoordinateSequence} in the result */
    public static final Geometry cloneGeometry(Geometry geom) {
        return cloneGeometry(geom, 2);
    }
    /** changes this to a new CSF -- more efficient than the JTS way */
    private static final Geometry cloneGeometry(Polygon geom, int dimension) {
        LinearRing lr = (LinearRing) cloneGeometry((LinearRing) geom.getExteriorRing(), dimension);
        LinearRing[] rings = new LinearRing[geom.getNumInteriorRing()];
        for (int t = 0; t < rings.length; t++) {
            rings[t] = (LinearRing) cloneGeometry((LinearRing) geom.getInteriorRingN(t), dimension);
        }
        return geomFac.createPolygon(lr, rings);
    }

    private static final Geometry cloneGeometry(Point geom, int dimension) {
        return geomFac.createPoint(
                new LiteCoordinateSequence(geom.getCoordinateSequence(), dimension));
    }

    private static final Geometry cloneGeometry(LineString geom, int dimension) {
        if (geom instanceof SingleCurvedGeometry) {
            SingleCurvedGeometry curved = (SingleCurvedGeometry) geom;
            double[] controlPoints = curved.getControlPoints();
            double[] clonedPoints = new double[controlPoints.length];
            System.arraycopy(controlPoints, 0, clonedPoints, 0, controlPoints.length);

            return new CircularString(clonedPoints, geomFac, curved.getTolerance());
        } else if (geom instanceof CompoundCurvedGeometry) {
            CompoundCurvedGeometry curved = (CompoundCurvedGeometry) geom;
            List components = curved.getComponents();
            List clonedComponents = new ArrayList<>(components.size());
            for (LineString ls : components) {
                LineString cloned = (LineString) cloneGeometry(ls, dimension);
                clonedComponents.add(cloned);
            }
            return new CompoundCurve(clonedComponents, geomFac, dimension);
        } else {
            return geomFac.createLineString(
                    new LiteCoordinateSequence(geom.getCoordinateSequence(), dimension));
        }
    }

    private static final Geometry cloneGeometry(LinearRing geom, int dimension) {
        if (geom instanceof SingleCurvedGeometry) {
            SingleCurvedGeometry curved = (SingleCurvedGeometry) geom;
            double[] controlPoints = curved.getControlPoints();
            double[] clonedPoints = new double[controlPoints.length];
            System.arraycopy(controlPoints, 0, clonedPoints, 0, controlPoints.length);

            return new CircularRing(clonedPoints, geomFac, curved.getTolerance());
        } else if (geom instanceof CompoundCurvedGeometry) {
            CompoundCurvedGeometry curved = (CompoundCurvedGeometry) geom;
            List components = curved.getComponents();
            List clonedComponents = new ArrayList<>(components.size());
            for (LineString ls : components) {
                LineString cloned = (LineString) cloneGeometry(ls, dimension);
                clonedComponents.add(cloned);
            }
            return new CompoundRing(clonedComponents, geomFac, dimension);
        } else {
            return geomFac.createLinearRing(
                    new LiteCoordinateSequence(geom.getCoordinateSequence(), dimension));
        }
    }

    private static final Geometry cloneGeometry(GeometryCollection geom, int dimension) {
        if (geom.getNumGeometries() == 0) {
            Geometry[] gs = new Geometry[0];
            return geomFac.createGeometryCollection(gs);
        }

        ArrayList gs = new ArrayList(geom.getNumGeometries());
        int n = geom.getNumGeometries();
        for (int t = 0; t < n; t++) {
            gs.add(cloneGeometry(geom.getGeometryN(t), dimension));
        }
        return geomFac.buildGeometry(gs);
    }

    public String toString() {
        if (size > 0) {
            StringBuffer strBuf = new StringBuffer((9 * dimension) * size);
            strBuf.append('(');
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < dimension; j++) {
                    strBuf.append(coords[i * dimension + j]);
                    if (j < dimension - 1) {
                        strBuf.append(" ");
                    }
                }
                if (i < size - 1) {
                    strBuf.append(", ");
                }
            }
            strBuf.append(')');
            return strBuf.toString();
        } else {
            return "()";
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy