/trunk/contribs/jts-source/com/vividsolutions/jts/geom/CoordinateArrays.java
Java | 437 lines | 208 code | 42 blank | 187 comment | 68 complexity | 104255dbb7ddf827de19a8ca18c88715 MD5 | raw file
-
-
- /*
- * The JTS Topology Suite is a collection of Java classes that
- * implement the fundamental operations required to validate a given
- * geo-spatial data set to a known topological specification.
- *
- * Copyright (C) 2001 Vivid Solutions
- *
- * 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; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For more information, contact:
- *
- * Vivid Solutions
- * Suite #1A
- * 2328 Government Street
- * Victoria BC V8T 5G5
- * Canada
- *
- * (250)385-6040
- * www.vividsolutions.com
- */
- package com.vividsolutions.jts.geom;
-
- import java.util.*;
-
- import com.vividsolutions.jts.math.MathUtil;
-
- /**
- * Useful utility functions for handling Coordinate arrays
- *
- * @version 1.7
- */
- public class CoordinateArrays {
-
- private final static Coordinate[] coordArrayType = new Coordinate[0];
-
- /**
- * Tests whether an array of {@link Coordinate}s forms a ring,
- * by checking length and closure.
- * Self-intersection is not checked.
- *
- * @param pts an array of Coordinates
- * @return true if the coordinate form a ring.
- */
- public static boolean isRing(Coordinate[] pts)
- {
- if (pts.length < 4) return false;
- if (! pts[0].equals2D(pts[pts.length -1])) return false;
- return true;
- }
-
- /**
- * Finds a point in a list of points which is not contained in another list of points
- * @param testPts the {@link Coordinate}s to test
- * @param pts an array of {@link Coordinate}s to test the input points against
- * @return a {@link Coordinate} from <code>testPts</code> which is not in <code>pts</code>, '
- * or <code>null</code>
- */
- public static Coordinate ptNotInList(Coordinate[] testPts, Coordinate[] pts)
- {
- for (int i = 0; i < testPts.length; i++) {
- Coordinate testPt = testPts[i];
- if (CoordinateArrays.indexOf(testPt, pts) < 0)
- return testPt;
- }
- return null;
- }
-
- /**
- * Compares two {@link Coordinate} arrays
- * in the forward direction of their coordinates,
- * using lexicographic ordering.
- *
- * @param pts1
- * @param pts2
- * @return an integer indicating the order
- */
- public static int compare(Coordinate[] pts1, Coordinate[] pts2) {
- int i = 0;
- while (i < pts1.length && i < pts2.length) {
- int compare = pts1[i].compareTo(pts2[i]);
- if (compare != 0)
- return compare;
- i++;
- }
- // handle situation when arrays are of different length
- if (i < pts2.length) return -1;
- if (i < pts1.length) return 1;
-
- return 0;
- }
-
- /**
- * A {@link Comparator} for {@link Coordinate} arrays
- * in the forward direction of their coordinates,
- * using lexicographic ordering.
- */
- public static class ForwardComparator
- implements Comparator
- {
- public int compare(Object o1, Object o2) {
- Coordinate[] pts1 = (Coordinate[]) o1;
- Coordinate[] pts2 = (Coordinate[]) o2;
-
- return CoordinateArrays.compare(pts1, pts2);
- }
- }
-
-
- /**
- * Determines which orientation of the {@link Coordinate} array
- * is (overall) increasing.
- * In other words, determines which end of the array is "smaller"
- * (using the standard ordering on {@link Coordinate}).
- * Returns an integer indicating the increasing direction.
- * If the sequence is a palindrome, it is defined to be
- * oriented in a positive direction.
- *
- * @param pts the array of Coordinates to test
- * @return <code>1</code> if the array is smaller at the start
- * or is a palindrome,
- * <code>-1</code> if smaller at the end
- */
- public static int increasingDirection(Coordinate[] pts) {
- for (int i = 0; i < pts.length / 2; i++) {
- int j = pts.length - 1 - i;
- // skip equal points on both ends
- int comp = pts[i].compareTo(pts[j]);
- if (comp != 0)
- return comp;
- }
- // array must be a palindrome - defined to be in positive direction
- return 1;
- }
-
- /**
- * Determines whether two {@link Coordinate} arrays of equal length
- * are equal in opposite directions.
- *
- * @param pts1
- * @param pts2
- * @return <code>true</code> if the two arrays are equal in opposite directions.
- */
- private static boolean isEqualReversed(Coordinate[] pts1, Coordinate[] pts2)
- {
- for (int i = 0; i < pts1.length; i++) {
- Coordinate p1 = pts1[i];
- Coordinate p2 = pts2[pts1.length - i - 1];
- if (p1.compareTo(p2) != 0)
- return false;
- }
- return true;
- }
-
- /**
- * A {@link Comparator} for {@link Coordinate} arrays
- * modulo their directionality.
- * E.g. if two coordinate arrays are identical but reversed
- * they will compare as equal under this ordering.
- * If the arrays are not equal, the ordering returned
- * is the ordering in the forward direction.
- *
- */
- public static class BidirectionalComparator
- implements Comparator
- {
- public int compare(Object o1, Object o2) {
- Coordinate[] pts1 = (Coordinate[]) o1;
- Coordinate[] pts2 = (Coordinate[]) o2;
-
- if (pts1.length < pts2.length) return -1;
- if (pts1.length > pts2.length) return 1;
-
- if (pts1.length == 0) return 0;
-
- int forwardComp = CoordinateArrays.compare(pts1, pts2);
- boolean isEqualRev = isEqualReversed(pts1, pts2);
- if (isEqualRev)
- return 0;
- return forwardComp;
- }
-
- public int OLDcompare(Object o1, Object o2) {
- Coordinate[] pts1 = (Coordinate[]) o1;
- Coordinate[] pts2 = (Coordinate[]) o2;
-
- if (pts1.length < pts2.length) return -1;
- if (pts1.length > pts2.length) return 1;
-
- if (pts1.length == 0) return 0;
-
- int dir1 = increasingDirection(pts1);
- int dir2 = increasingDirection(pts2);
-
- int i1 = dir1 > 0 ? 0 : pts1.length - 1;
- int i2 = dir2 > 0 ? 0 : pts1.length - 1;
-
- for (int i = 0; i < pts1.length; i++) {
- int comparePt = pts1[i1].compareTo(pts2[i2]);
- if (comparePt != 0)
- return comparePt;
- i1 += dir1;
- i2 += dir2;
- }
- return 0;
- }
-
- }
-
- /**
- * Creates a deep copy of the argument {@link Coordinate} array.
- *
- * @param coordinates an array of Coordinates
- * @return a deep copy of the input
- */
- public static Coordinate[] copyDeep(Coordinate[] coordinates) {
- Coordinate[] copy = new Coordinate[coordinates.length];
- for (int i = 0; i < coordinates.length; i++) {
- copy[i] = new Coordinate(coordinates[i]);
- }
- return copy;
- }
-
- /**
- * Creates a deep copy of a given section of a source {@link Coordinate} array
- * into a destination Coordinate array.
- * The destination array must be an appropriate size to receive
- * the copied coordinates.
- *
- * @param src an array of Coordinates
- * @param srcStart the index to start copying from
- * @param dest the
- * @param destStart the destination index to start copying to
- * @param length the number of items to copy
- */
- public static void copyDeep(Coordinate[] src, int srcStart, Coordinate[] dest, int destStart, int length) {
- for (int i = 0; i < length; i++) {
- dest[destStart + i] = new Coordinate(src[srcStart + i]);
- }
- }
-
- /**
- * Converts the given Collection of Coordinates into a Coordinate array.
- */
- public static Coordinate[] toCoordinateArray(Collection coordList)
- {
- return (Coordinate[]) coordList.toArray(coordArrayType);
- }
-
- /**
- * Returns whether #equals returns true for any two consecutive Coordinates
- * in the given array.
- */
- public static boolean hasRepeatedPoints(Coordinate[] coord)
- {
- for (int i = 1; i < coord.length; i++) {
- if (coord[i - 1].equals(coord[i]) ) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns either the given coordinate array if its length is greater than the
- * given amount, or an empty coordinate array.
- */
- public static Coordinate[] atLeastNCoordinatesOrNothing(int n, Coordinate[] c) {
- return c.length >= n ? c : new Coordinate[] { };
- }
-
- /**
- * If the coordinate array argument has repeated points,
- * constructs a new array containing no repeated points.
- * Otherwise, returns the argument.
- * @see #hasRepeatedPoints(Coordinate[])
- */
- public static Coordinate[] removeRepeatedPoints(Coordinate[] coord)
- {
- if (! hasRepeatedPoints(coord)) return coord;
- CoordinateList coordList = new CoordinateList(coord, false);
- return coordList.toCoordinateArray();
- }
-
- /**
- * Reverses the coordinates in an array in-place.
- */
- public static void reverse(Coordinate[] coord)
- {
- int last = coord.length - 1;
- int mid = last / 2;
- for (int i = 0; i <= mid; i++) {
- Coordinate tmp = coord[i];
- coord[i] = coord[last - i];
- coord[last - i] = tmp;
- }
- }
-
- /**
- * Returns true if the two arrays are identical, both null, or pointwise
- * equal (as compared using Coordinate#equals)
- * @see Coordinate#equals(Object)
- */
- public static boolean equals(
- Coordinate[] coord1,
- Coordinate[] coord2)
- {
- if (coord1 == coord2) return true;
- if (coord1 == null || coord2 == null) return false;
- if (coord1.length != coord2.length) return false;
- for (int i = 0; i < coord1.length; i++) {
- if (! coord1[i].equals(coord2[i])) return false;
- }
- return true;
- }
-
- /**
- * Returns true if the two arrays are identical, both null, or pointwise
- * equal, using a user-defined {@link Comparator} for {@link Coordinate} s
- *
- * @param coord1 an array of Coordinates
- * @param coord2 an array of Coordinates
- * @param coordinateComparator a Comparator for Coordinates
- */
- public static boolean equals(
- Coordinate[] coord1,
- Coordinate[] coord2,
- Comparator coordinateComparator)
- {
- if (coord1 == coord2) return true;
- if (coord1 == null || coord2 == null) return false;
- if (coord1.length != coord2.length) return false;
- for (int i = 0; i < coord1.length; i++) {
- if (coordinateComparator.compare(coord1[i], coord2[i]) != 0)
- return false;
- }
- return true;
- }
-
- /**
- * Returns the minimum coordinate, using the usual lexicographic comparison.
- *
- *@param coordinates the array to search
- *@return the minimum coordinate in the array, found using <code>compareTo</code>
- *@see Coordinate#compareTo(Object)
- */
- public static Coordinate minCoordinate(Coordinate[] coordinates)
- {
- Coordinate minCoord = null;
- for (int i = 0; i < coordinates.length; i++) {
- if (minCoord == null || minCoord.compareTo(coordinates[i]) > 0) {
- minCoord = coordinates[i];
- }
- }
- return minCoord;
- }
- /**
- * Shifts the positions of the coordinates until <code>firstCoordinate</code>
- * is first.
- *
- *@param coordinates the array to rearrange
- *@param firstCoordinate the coordinate to make first
- */
- public static void scroll(Coordinate[] coordinates, Coordinate firstCoordinate) {
- int i = indexOf(firstCoordinate, coordinates);
- if (i < 0) return;
- Coordinate[] newCoordinates = new Coordinate[coordinates.length];
- System.arraycopy(coordinates, i, newCoordinates, 0, coordinates.length - i);
- System.arraycopy(coordinates, 0, newCoordinates, coordinates.length - i, i);
- System.arraycopy(newCoordinates, 0, coordinates, 0, coordinates.length);
- }
-
- /**
- * Returns the index of <code>coordinate</code> in <code>coordinates</code>.
- * The first position is 0; the second, 1; etc.
- *
- *@param coordinate the <code>Coordinate</code> to search for
- *@param coordinates the array to search
- *@return the position of <code>coordinate</code>, or -1 if it is
- * not found
- */
- public static int indexOf(Coordinate coordinate, Coordinate[] coordinates) {
- for (int i = 0; i < coordinates.length; i++) {
- if (coordinate.equals(coordinates[i])) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Extracts a subsequence of the input {@link Coordinate} array
- * from indices <code>start</code> to
- * <code>end</code> (inclusive).
- * The input indices are clamped to the array size;
- * If the end index is less than the start index,
- * the extracted array will be empty.
- *
- * @param pts the input array
- * @param start the index of the start of the subsequence to extract
- * @param end the index of the end of the subsequence to extract
- * @return a subsequence of the input array
- */
- public static Coordinate[] extract(Coordinate[] pts, int start, int end)
- {
- start = MathUtil.clamp(start, 0, pts.length);
- end = MathUtil.clamp(end, -1, pts.length);
-
- int npts = end - start + 1;
- if (end < 0) npts = 0;
- if (start >= pts.length) npts = 0;
- if (end < start) npts = 0;
-
- Coordinate[] extractPts = new Coordinate[npts];
- if (npts == 0) return extractPts;
-
- int iPts = 0;
- for (int i = start; i <= end; i++) {
- extractPts[iPts++] = pts[i];
- }
- return extractPts;
- }
-
- }