/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2005-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. */ /* * $ Id $ * $ Source $ * Created on May 5, 2005 */ package org.geotools.geometry.jts.spatialschema.geometry; //J2SE dependencies import java.awt.geom.Point2D; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; // OpenGIS dependencies import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.MismatchedDimensionException; //geotools JTS wrappers dependency import org.geotools.geometry.jts.GeometryUtils; /** * Holds the coordinates for a two-dimensional position within some coordinate reference system. * This class put no restriction on the axis order, i.e. it doesn't ensure that the value stored * in the {@linkplain #x x} field increases toward {@linkplain AxisDirection#EAST East} and the * value in the {@linkplain #y y} field toward {@linkplain AxisDirection#NORTH North}. The rational * is that other {@link DirectPosition} implementation do not have restriction on axis order, and * anyway such a restriction is hard to generalize (what to do with * {@linkplain AxisDirection#NORTH_EAST North-East} direction?). * * * * * @source $URL$ * @version $Id$ * @author Martin Desruisseaux */ public class DirectPosition2D extends Point2D.Double implements DirectPosition, Serializable { /** * The coordinate reference system for this position; */ private CoordinateReferenceSystem crs; /** * Construct a position initialized to (0,0) with a {@code null} * coordinate reference system. */ public DirectPosition2D() { } /** * Construct a position with the specified coordinate reference system. */ public DirectPosition2D(final CoordinateReferenceSystem crs) { setCoordinateReferenceSystem(crs); } /** * Construct a 2D position from the specified ordinates. */ public DirectPosition2D(final double x, final double y) { super(x,y); } /** * Construct a 2D position from the specified ordinates in the specified CRS. */ public DirectPosition2D(final CoordinateReferenceSystem crs, final double x, final double y) { super(x,y); setCoordinateReferenceSystem(crs); } /** * Construct a position from the specified {@link Point2D}. */ public DirectPosition2D(final Point2D point) { super(point.getX(), point.getY()); if (point instanceof DirectPosition) { setCoordinateReferenceSystem(((DirectPosition) point).getCoordinateReferenceSystem()); } } /** * Construct a position initialized to the same values than the specified point. */ public DirectPosition2D(final DirectPosition point) { setLocation(point); } /** * Returns always {@code this}, the direct position for this * {@linkplain org.opengis.geometry.coordinate.Position position}. */ @Deprecated public DirectPosition getPosition() { return this; } /** * Returns always {@code this}, the direct position for this * {@linkplain org.opengis.geometry.coordinate.Position position}. */ public DirectPosition getDirectPosition() { return this; } /** * Returns the coordinate reference system in which the coordinate is given. * May be {@code null} if this particular {@code DirectPosition} is included * in a larger object with such a reference to a {@linkplain CoordinateReferenceSystem * coordinate reference system}. * * @return The coordinate reference system, or {@code null}. */ public final CoordinateReferenceSystem getCoordinateReferenceSystem() { return crs; } /** * Set the coordinate reference system in which the coordinate is given. * * @param crs The new coordinate reference system, or {@code null}. */ public void setCoordinateReferenceSystem(final CoordinateReferenceSystem crs) { GeometryUtils.checkDimension("dimension", crs, 2); this.crs = crs; } /** * The length of coordinate sequence (the number of entries). * This is always 2 for {@code DirectPosition2D} objects. * * @return The dimensionality of this position. */ public final int getDimension() { return 2; } /** * Returns a sequence of numbers that hold the coordinate of this position in its * reference system. * * @return The coordinates */ public double[] getCoordinate() { return new double[] {x,y}; } @Deprecated public double[] getCoordinates() { return getCoordinate(); } /** * Returns the ordinate at the specified dimension. * * @param dimension The dimension in the range 0 to 1 inclusive. * @return The coordinate at the specified dimension. * @throws IndexOutOfBoundsException if the specified dimension is out of bounds. * * @todo Provides a more detailled error message. */ public final double getOrdinate(final int dimension) throws IndexOutOfBoundsException { switch (dimension) { case 0: return x; case 1: return y; default: throw new IndexOutOfBoundsException(String.valueOf(dimension)); } } /** * Sets the ordinate value along the specified dimension. * * @param dimension the dimension for the ordinate of interest. * @param value the ordinate value of interest. * @throws IndexOutOfBoundsException if the specified dimension is out of bounds. * * @todo Provides a more detailled error message. */ public final void setOrdinate(int dimension, double value) throws IndexOutOfBoundsException { switch (dimension) { case 0: x=value; break; case 1: y=value; break; default: throw new IndexOutOfBoundsException(String.valueOf(dimension)); } } /** * Set this coordinate to the specified direct position. If the specified position * contains a {@linkplain CoordinateReferenceSystem coordinate reference system}, * then the CRS for this position will be set to the CRS of the specified position. * * @param position The new position for this point. * @throws MismatchedDimensionException if this point doesn't have the expected dimension. */ public void setLocation(final DirectPosition position) throws MismatchedDimensionException { GeometryUtils.ensureDimensionMatch("position", position.getDimension(), 2); setCoordinateReferenceSystem(position.getCoordinateReferenceSystem()); x = position.getOrdinate(0); y = position.getOrdinate(1); } /** * Returns a {@link Point2D} with the same coordinate as this direct position. */ public Point2D toPoint2D() { return new Point2D.Double(x,y); } /** * Returns a string representation of this coordinate. The returned string is * implementation dependent. It is usually provided for debugging purposes. */ public String toString() { return toString(this, getCoordinates()); } /** * Returns a hash value for this coordinate. This value need not remain consistent between * different implementations of the same class. */ public int hashCode() { int code = super.hashCode(); if (crs != null) { code ^= crs.hashCode(); } return code; } @Override public DirectPosition2D clone() { return (DirectPosition2D) super.clone(); } /** * Write this object to the specified stream. This method is necessary * because the super-class is not serializable. */ private void writeObject(final ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeDouble(x); out.writeDouble(y); } /** * Read this object from the specified stream. This method is necessary * because the super-class is not serializable. */ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); x = in.readDouble(); y = in.readDouble(); } /** * Returns a string representation of an object. The returned string is implementation * dependent. It is usually provided for debugging purposes. */ static String toString(final Object owner, final double[] ordinates) { final StringBuffer buffer = new StringBuffer(owner.toString());//new StringBuffer(Utilities.getShortClassName(owner)); buffer.append('['); for (int i=0; i<ordinates.length; i++) { if (i!=0) buffer.append(", "); buffer.append(ordinates[i]); } buffer.append(']'); return buffer.toString(); } }