/* * 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.revolsys.geometry.noding; import com.revolsys.geometry.model.LineString; /** * Allows comparing {@link Coordinates} arrays * in an orientation-independent way. * * @author Martin Davis * @version 1.7 */ public class OrientedCoordinateArray implements Comparable<OrientedCoordinateArray> { /** * Determines which orientation of the {@link Coordinates} array * is (overall) increasing. * In other words, determines which end of the array is "smaller" * (using the standard ordering on {@link Coordinates}). * Returns an integer indicating the increasing direction. * If the sequence is a palindrome, it is defined to be * oriented in a positive direction. * * @param line the array of Point 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(final LineString line) { final int numPoints = line.getVertexCount(); for (int vertextIndex = 0; vertextIndex < numPoints / 2; vertextIndex++) { final int j = numPoints - 1 - vertextIndex; // skip equal points on both ends final int comp = line.compareVertex(vertextIndex, j); if (comp != 0) { return comp; } } // array must be a palindrome - defined to be in positive direction return 1; } private final boolean orientation; private final LineString points; /** * Creates a new {@link OrientedCoordinateArray} * for the given {@link Coordinates} array. * * @param points the coordinates to orient */ public OrientedCoordinateArray(final LineString points) { this.points = points; this.orientation = increasingDirection(points) == 1; } /** * Compares two {@link OrientedCoordinateArray}s for their relative order * * @return -1 this one is smaller; * 0 the two objects are equal; * 1 this one is greater */ @Override public int compareTo(final OrientedCoordinateArray oca) { final LineString points1 = getPoints(); final LineString points2 = oca.getPoints(); final boolean orientation2 = oca.getOrientation(); final int dir1 = this.orientation ? 1 : -1; final int dir2 = orientation2 ? 1 : -1; final int vertexCount1 = points1.getVertexCount(); final int vertexCount2 = points2.getVertexCount(); final int limit1 = this.orientation ? vertexCount1 : -1; final int limit2 = orientation2 ? vertexCount2 : -1; int i1 = this.orientation ? 0 : vertexCount1 - 1; int i2 = orientation2 ? 0 : vertexCount2 - 1; while (true) { final int compPt = points1.compareVertex(i1, points2, i2); if (compPt != 0) { return compPt; } else { i1 += dir1; i2 += dir2; final boolean done1 = i1 == limit1; final boolean done2 = i2 == limit2; if (done1 && !done2) { return -1; } else if (!done1 && done2) { return 1; } else if (done1 && done2) { return 0; } } } } public boolean getOrientation() { return this.orientation; } public LineString getPoints() { return this.points; } }