/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2006-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.
*/
package org.geotools.coverage.grid;
import java.io.Serializable;
import java.util.Arrays;
import org.opengis.coverage.grid.Grid;
import org.opengis.coverage.grid.GridPoint;
import org.opengis.coverage.grid.GridCoordinates;
import org.geotools.resources.Classes;
/**
* Holds the set of grid coordinates that specifies the location of the
* {@linkplain GridPoint grid point} within the {@linkplain Grid grid}.
*
* @since 2.4
* @source $URL$
* @version $Id$
* @author Martin Desruisseaux
*
* @see GridCoordinates2D
*/
public class GeneralGridCoordinates implements GridCoordinates, Serializable {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = 8146318677770695383L;
/**
* The grid coordinates.
*/
final int[] coordinates;
/**
* Creates a grid coordinates of the specified dimension.
* All coordinates are initially set to 0.
*
* @param dimension The number of dimension.
*/
public GeneralGridCoordinates(final int dimension) {
coordinates = new int[dimension];
}
/**
* Creates a grid coordinates initialized to the specified values.
*
* @param coordinates The grid coordinates to copy.
*/
public GeneralGridCoordinates(final int[] coordinates) {
this.coordinates = coordinates.clone();
}
/**
* Creates a grid coordinates initialized to the specified values in the specified range.
*
* @param coordinates The coordinates to copy.
* @param lower Index of the first value to copy, inclusive.
* @param upper Index of the last value to copy, exclusive.
*
* @since 2.5
*/
public GeneralGridCoordinates(final int[] coordinates, final int lower, final int upper) {
final int length = upper - lower;
this.coordinates = new int[length];
System.arraycopy(coordinates, lower, this.coordinates, 0, length);
}
/**
* Creates a grid coordinates which is a copy of the specified one.
*
* @param coordinates The grid coordinates to copy.
*
* @since 2.5
*/
public GeneralGridCoordinates(final GridCoordinates coordinates) {
this.coordinates = coordinates.getCoordinateValues();
}
/**
* Returns the number of dimensions. This method is equivalent to
* <code>{@linkplain #getCoordinateValues()}.length</code>. It is
* provided for efficienty.
*/
public int getDimension() {
return coordinates.length;
}
/**
* Returns one integer value for each dimension of the grid. The ordering of these coordinate
* values shall be the same as that of the elements of {@link Grid#getAxisNames}. The value of
* a single coordinate shall be the number of offsets from the origin of the grid in the
* direction of a specific axis.
*
* @return A copy of the coordinates. Changes in the returned array will not be reflected
* back in this {@code GeneralGridCoordinates} object.
*/
public int[] getCoordinateValues() {
return coordinates.clone();
}
/**
* Returns the coordinate value at the specified dimension. This method is equivalent to
* <code>{@linkplain #getCoordinateValues()}[<var>i</var>]</code>. It is provided for
* efficienty.
*
* @param dimension The dimension from 0 inclusive to {@link #getDimension} exclusive.
* @return The value at the requested dimension.
* @throws ArrayIndexOutOfBoundsException if the specified dimension is out of bounds.
*/
public int getCoordinateValue(final int dimension) throws ArrayIndexOutOfBoundsException {
return coordinates[dimension];
}
/**
* Sets the coordinate value at the specified dimension (optional operation).
*
* @param dimension The index of the value to set.
* @param value The new value.
* @throws ArrayIndexOutOfBoundsException if the specified dimension is out of bounds.
* @throws UnsupportedOperationException if this grid coordinates is not modifiable.
*/
public void setCoordinateValue(final int dimension, final int value)
throws ArrayIndexOutOfBoundsException, UnsupportedOperationException
{
coordinates[dimension] = value;
}
/**
* Returns a string representation of the specified grid coordinates.
*/
static String toString(final GridCoordinates coordinates) {
final StringBuilder buffer = new StringBuilder(Classes.getShortClassName(coordinates));
final int dimension = coordinates.getDimension();
for (int i=0; i<dimension; i++) {
buffer.append(i==0 ? '[' : ',').append(coordinates.getCoordinateValue(i));
}
return buffer.append(']').toString();
}
/**
* Returns a string representation of this grid coordinates.
*/
@Override
public String toString() {
return toString(this);
}
/**
* Returns a hash code value for this object.
*
* @todo Use {@link Arrays#hashCode(int[])} when we will be allowed to compile for J2SE 1.5.
*/
@Override
public int hashCode() {
int code = (int) serialVersionUID;
for (int i=0; i<coordinates.length; i++) {
code = code * 37 + coordinates[i];
}
return code;
}
/**
* Compares this grid coordinates with the specified object for equality.
*
* @param object The object to compares with this grid coordinates.
* @return {@code true} if the given object is equals to this grid coordinates.
*/
@Override
public boolean equals(final Object object) {
if (object == this) {
// Slight optimization.
return true;
}
// We do not require the exact same class because we that that clones of
// immutable grid coordinates to be equal to their original coordinates.
if (object instanceof GeneralGridCoordinates) {
final GeneralGridCoordinates that = (GeneralGridCoordinates) object;
return Arrays.equals(this.coordinates, that.coordinates);
}
return false;
}
/**
* Returns a clone of this grid coordinates.
*
* @return A clone of this grid coordinates.
*/
@Override
public GeneralGridCoordinates clone() {
try {
return (GeneralGridCoordinates) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
/**
* An immutable {@link GridCoordinates}. This is sometime useful for creating a single
* instance to be shared by many objects without the cost of cloning. This class is
* final in order to prevent subclasses from making it mutable again.
*
* @since 2.5
* @source $URL$
* @version $Id$
* @author Martin Desruisseaux
*/
public static final class Immutable extends GeneralGridCoordinates {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = -7723383411061425866L;
/**
* Creates an immutable grid coordinates with the specified values.
*
* @param coordinates The grid coordinates to copy.
*/
public Immutable(final int[] coordinates) {
super(coordinates);
}
/**
* Creates an immutable grid coordinates with the specified values in the specified range.
*
* @param coordinates The coordinates to copy.
* @param lower Index of the first value to copy, inclusive.
* @param upper Index of the last value to copy, exclusive.
*/
public Immutable(final int[] coordinates, final int lower, final int upper) {
super(coordinates, lower, upper);
}
/**
* Creates an immutable grid coordinates with the specified values.
*
* @param coordinates The grid coordinates to copy.
*/
public Immutable(final GridCoordinates coordinates) {
super(coordinates);
}
/**
* Translates all ordinate values by the given offset. This method is for internal usage by
* {@link GeneralGridEnvelope} only, to be invoked only right after construction and before
* the instance goes public. This method should not be public since it breaks the
* immutability contract.
*/
final void translate(final int offset) {
for (int i=0; i<coordinates.length; i++) {
coordinates[i] += offset;
}
}
/**
* Do not allows modification of this grid coordinates.
*
* @throws UnsupportedOperationException always thrown.
*/
@Override
public void setCoordinateValue(final int dimension, final int value)
throws UnsupportedOperationException
{
throw new UnsupportedOperationException();
}
/**
* Returns a mutable clone of this grid coordinates. The clone is an instance of
* {@link GeneralGridCoordinates} rather than this {@code Immutable} subclass.
*
* @return A mutable clone of this grid coordinates.
*/
@Override
public GeneralGridCoordinates clone() {
return new GeneralGridCoordinates(coordinates);
}
}
}