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

com.vividsolutions.jts.geom.Coordinate Maven / Gradle / Ivy

There is a newer version: 0.1.4
Show newest version
/*
* 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.io.Serializable;
import java.util.Comparator;
import com.vividsolutions.jts.util.Assert;
import com.vividsolutions.jts.util.NumberUtil;


/**
 * A lightweight class used to store coordinates
 * on the 2-dimensional Cartesian plane.
 * It is distinct from {@link Point}, which is a subclass of {@link Geometry}. 
 * Unlike objects of type {@link Point} (which contain additional
 * information such as an envelope, a precision model, and spatial reference
 * system information), a Coordinate only contains ordinate values
 * and accessor methods. 

* * Coordinates are two-dimensional points, with an additional Z-ordinate. * If an Z-ordinate value is not specified or not defined, * constructed coordinates have a Z-ordinate of NaN * (which is also the value of NULL_ORDINATE). * The standard comparison functions ignore the Z-ordinate. * Apart from the basic accessor functions, JTS supports * only specific operations involving the Z-ordinate. * *@version 1.7 */ public class Coordinate implements Comparable, Cloneable, Serializable { private static final long serialVersionUID = 6683108902428366910L; /** * The value used to indicate a null or missing ordinate value. * In particular, used for the value of ordinates for dimensions * greater than the defined dimension of a coordinate. */ public static final double NULL_ORDINATE = Double.NaN; /** * Standard ordinate index values */ public static final int X = 0; public static final int Y = 1; public static final int Z = 2; /** * The x-coordinate. */ public double x; /** * The y-coordinate. */ public double y; /** * The z-coordinate. */ public double z; /** * Constructs a Coordinate at (x,y,z). * *@param x the x-value *@param y the y-value *@param z the z-value */ public Coordinate(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } /** * Constructs a Coordinate at (0,0,NaN). */ public Coordinate() { this(0.0, 0.0); } /** * Constructs a Coordinate having the same (x,y,z) values as * other. * *@param c the Coordinate to copy. */ public Coordinate(Coordinate c) { this(c.x, c.y, c.z); } /** * Constructs a Coordinate at (x,y,NaN). * *@param x the x-value *@param y the y-value */ public Coordinate(double x, double y) { this(x, y, NULL_ORDINATE); } /** * Sets this Coordinates (x,y,z) values to that of other. * *@param other the Coordinate to copy */ public void setCoordinate(Coordinate other) { x = other.x; y = other.y; z = other.z; } /** * Gets the ordinate value for the given index. * The supported values for the index are * {@link X}, {@link Y}, and {@link Z}. * * @param ordinateIndex the ordinate index * @return the value of the ordinate * @throws IllegalArgumentException if the index is not valid */ public double getOrdinate(int ordinateIndex) { switch (ordinateIndex) { case X: return x; case Y: return y; case Z: return z; } throw new IllegalArgumentException("Invalid ordinate index: " + ordinateIndex); } /** * Sets the ordinate for the given index * to a given value. * The supported values for the index are * {@link X}, {@link Y}, and {@link Z}. * * @param ordinateIndex the ordinate index * @param value the value to set * @throws IllegalArgumentException if the index is not valid */ public void setOrdinate(int ordinateIndex, double value) { switch (ordinateIndex) { case X: x = value; break; case Y: y = value; break; case Z: z = value; break; default: throw new IllegalArgumentException("Invalid ordinate index: " + ordinateIndex); } } /** * Returns whether the planar projections of the two Coordinates * are equal. * *@param other a Coordinate with which to do the 2D comparison. *@return true if the x- and y-coordinates are equal; the * z-coordinates do not have to be equal. */ public boolean equals2D(Coordinate other) { if (x != other.x) { return false; } if (y != other.y) { return false; } return true; } /** * Tests if another coordinate has the same values for the X and Y ordinates. * The Z ordinate is ignored. * *@param other a Coordinate with which to do the 2D comparison. *@return true if other is a Coordinate * with the same values for X and Y. */ public boolean equals2D(Coordinate c, double tolerance){ if (! NumberUtil.equalsWithTolerance(this.x, c.x, tolerance)) { return false; } if (! NumberUtil.equalsWithTolerance(this.y, c.y, tolerance)) { return false; } return true; } /** * Tests if another coordinate has the same values for the X, Y and Z ordinates. * *@param other a Coordinate with which to do the 3D comparison. *@return true if other is a Coordinate * with the same values for X, Y and Z. */ public boolean equals3D(Coordinate other) { return (x == other.x) && (y == other.y) && ((z == other.z) || (Double.isNaN(z) && Double.isNaN(other.z))); } /** * Tests if another coordinate has the same value for Z, within a tolerance. * * @param c a coordinate * @param tolerance the tolerance value * @return true if the Z ordinates are within the given tolerance */ public boolean equalInZ(Coordinate c, double tolerance){ return NumberUtil.equalsWithTolerance(this.z, c.z, tolerance); } /** * Returns true if other has the same values for * the x and y ordinates. * Since Coordinates are 2.5D, this routine ignores the z value when making the comparison. * *@param other a Coordinate with which to do the comparison. *@return true if other is a Coordinate * with the same values for the x and y ordinates. */ public boolean equals(Object other) { if (!(other instanceof Coordinate)) { return false; } return equals2D((Coordinate) other); } /** * Compares this {@link Coordinate} with the specified {@link Coordinate} for order. * This method ignores the z value when making the comparison. * Returns: *

    *
  • -1 : this.x < other.x || ((this.x == other.x) && (this.y < * other.y)) *
  • 0 : this.x == other.x && this.y = other.y *
  • 1 : this.x > other.x || ((this.x == other.x) && (this.y > other.y)) * *
* Note: This method assumes that ordinate values * are valid numbers. NaN values are not handled correctly. * *@param o the Coordinate with which this Coordinate * is being compared *@return -1, zero, or 1 as this Coordinate * is less than, equal to, or greater than the specified Coordinate */ public int compareTo(Object o) { Coordinate other = (Coordinate) o; if (x < other.x) return -1; if (x > other.x) return 1; if (y < other.y) return -1; if (y > other.y) return 1; return 0; } /** * Returns a String of the form (x,y,z) . * *@return a String of the form (x,y,z) */ public String toString() { return "(" + x + ", " + y + ", " + z + ")"; } public Object clone() { try { Coordinate coord = (Coordinate) super.clone(); return coord; // return the clone } catch (CloneNotSupportedException e) { Assert.shouldNeverReachHere( "this shouldn't happen because this class is Cloneable"); return null; } } /** * Computes the 2-dimensional Euclidean distance to another location. * The Z-ordinate is ignored. * * @param c a point * @return the 2-dimensional Euclidean distance between the locations */ public double distance(Coordinate c) { double dx = x - c.x; double dy = y - c.y; return Math.sqrt(dx * dx + dy * dy); } /** * Computes the 3-dimensional Euclidean distance to another location. * * @param c a coordinate * @return the 3-dimensional Euclidean distance between the locations */ public double distance3D(Coordinate c) { double dx = x - c.x; double dy = y - c.y; double dz = z - c.z; return Math.sqrt(dx * dx + dy * dy + dz * dz); } /** * Gets a hashcode for this coordinate. * * @return a hashcode for this coordinate */ public int hashCode() { //Algorithm from Effective Java by Joshua Bloch [Jon Aquino] int result = 17; result = 37 * result + hashCode(x); result = 37 * result + hashCode(y); return result; } /** * Computes a hash code for a double value, using the algorithm from * Joshua Bloch's book Effective Java" * * @return a hashcode for the double value */ public static int hashCode(double x) { long f = Double.doubleToLongBits(x); return (int)(f^(f>>>32)); } /** * Compares two {@link Coordinate}s, allowing for either a 2-dimensional * or 3-dimensional comparison, and handling NaN values correctly. */ public static class DimensionalComparator implements Comparator { /** * Compare two doubles, allowing for NaN values. * NaN is treated as being less than any valid number. * * @param a a double * @param b a double * @return -1, 0, or 1 depending on whether a is less than, equal to or greater than b */ public static int compare(double a, double b) { if (a < b) return -1; if (a > b) return 1; if (Double.isNaN(a)) { if (Double.isNaN(b)) return 0; return -1; } if (Double.isNaN(b)) return 1; return 0; } private int dimensionsToTest = 2; /** * Creates a comparator for 2 dimensional coordinates. */ public DimensionalComparator() { this(2); } /** * Creates a comparator for 2 or 3 dimensional coordinates, depending * on the value provided. * * @param dimensionsToTest the number of dimensions to test */ public DimensionalComparator(int dimensionsToTest) { if (dimensionsToTest != 2 && dimensionsToTest != 3) throw new IllegalArgumentException("only 2 or 3 dimensions may be specified"); this.dimensionsToTest = dimensionsToTest; } /** * Compares two {@link Coordinate}s along to the number of * dimensions specified. * * @param o1 a {@link Coordinate} * @param o2 a {link Coordinate} * @return -1, 0, or 1 depending on whether o1 is less than, * equal to, or greater than 02 * */ public int compare(Object o1, Object o2) { Coordinate c1 = (Coordinate) o1; Coordinate c2 = (Coordinate) o2; int compX = compare(c1.x, c2.x); if (compX != 0) return compX; int compY = compare(c1.y, c2.y); if (compY != 0) return compY; if (dimensionsToTest <= 2) return 0; int compZ = compare(c1.z, c2.z); return compZ; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy