/* * Geotools 2 - OpenSource mapping toolkit * (C) 2003, Geotools Project Managment Committee (PMC) * (C) 2001, Institut de Recherche pour le Développement * * 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 */ package org.geotools.pt; // Miscellaneous import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.util.Arrays; import org.geotools.resources.i18n.ErrorKeys; import org.geotools.resources.i18n.Errors; import org.geotools.resources.geometry.XRectangle2D; import org.opengis.spatialschema.geometry.DirectPosition; import org.opengis.spatialschema.geometry.MismatchedDimensionException; import org.opengis.util.Cloneable; /** * A box defined by two positions. The two positions must have the * same dimension. Each of the ordinate values in the minimum point * must be less than or equal to the corresponding ordinate value * in the maximum point. Please note that these two points may be * outside the valid domain of their coordinate system. (Of course * the points and envelope do not explicitly reference a coordinate * system, but their implicit coordinate system is defined by their * context.) * * @source $URL$ * @version 1.00 * @author OpenGIS (www.opengis.org) * @author Martin Desruisseaux * * @see org.opengis.pt.PT_Envelope * @see java.awt.geom.Rectangle2D * * @deprecated Replaced by {@link org.geotools.geometry.GeneralEnvelope} * in the org.geotools.geometry package. */ public class Envelope implements org.opengis.spatialschema.geometry.Envelope, Dimensioned, Cloneable, Serializable { /** * Serial number for interoperability with different versions. */ private static final long serialVersionUID = -3228667532994790309L; /** * Minimum and maximum ordinate values. The first half contains minimum * ordinates, while the last half contains maximum ordinates. */ private final double[] ord; /** * Check if ordinate values in the minimum point are less than or * equal to the corresponding ordinate value in the maximum point. * * @throws IllegalArgumentException if an ordinate value in the minimum * point is not less than or equal to the corresponding ordinate * value in the maximum point. */ private void checkCoherence() throws IllegalArgumentException { final int dimension = ord.length/2; for (int i=0; i= 0) { return ord[dimension + ord.length/2]; } else { throw new ArrayIndexOutOfBoundsException(dimension); } } /** * Returns the center ordinate * along the specified dimension. */ public double getCenter(final int dimension) { return 0.5*(ord[dimension] + ord[dimension+ord.length/2]); } /** * Returns the envelope length along the specified dimension. * This length is equals to the maximum ordinate minus the * minimal ordinate. */ public double getLength(final int dimension) { return ord[dimension+ord.length/2] - ord[dimension]; } /** * Set the envelope's range along the specified dimension. * * @param dimension The dimension to set. * @param minimum The minimum value along the specified dimension. * @param maximum The maximum value along the specified dimension. */ public void setRange(final int dimension, double minimum, double maximum) { if (minimum > maximum) { // Make an empty envelope (min==max) // while keeping it legal (min<=max). minimum = maximum = 0.5*(minimum+maximum); } if (dimension>=0) { // Do not make any change if 'dimension' is out of range. ord[dimension+ord.length/2] = maximum; ord[dimension ] = minimum; } else { throw new ArrayIndexOutOfBoundsException(dimension); } } /** * Adds a point to this envelope. The resulting envelope * is the smallest envelope that contains both the original envelope and the * specified point. After adding a point, a call to {@link #contains} with the * added point as an argument will return true, except if one of * the point's ordinates was {@link Double#NaN} (in which case the corresponding * ordinate have been ignored). * * @param point The point to add. * @throws MismatchedDimensionException if the specified point doesn't have * the expected dimension. */ public void add(final CoordinatePoint point) throws MismatchedDimensionException { final int dim = ord.length/2; point.ensureDimensionMatch(dim); for (int i=0; i ord[i+dim]) ord[i+dim]=value; } } /** * Adds an envelope object to this envelope. * The resulting envelope is the union of the * two Envelope objects. * * @param envelope the Envelope to add to this envelope. * @throws MismatchedDimensionException if the specified envelope doesn't * have the expected dimension. */ public void add(final Envelope envelope) throws MismatchedDimensionException { final int dim = ord.length/2; envelope.ensureDimensionMatch(dim); for (int i=0; i ord[i+dim]) ord[i+dim]=max; } } /** * Tests if a specified coordinate is inside the boundary of this envelope. * * @param point The point to text. * @return true if the specified coordinates are inside the boundary * of this envelope; false otherwise. * @throws MismatchedDimensionException if the specified point doesn't have * the expected dimension. */ public boolean contains(final CoordinatePoint point) throws MismatchedDimensionException { final int dimension = ord.length/2; point.ensureDimensionMatch(dimension); for (int i=0; i= ord[i ])) return false; if (!(value <= ord[i+dimension])) return false; // Use '!' in order to take 'NaN' in account. } return true; } /** * Set this envelope to the intersection if this envelope with the specified one. * * @param envelope the Envelope to intersect to this envelope. * @throws MismatchedDimensionException if the specified envelope doesn't * have the expected dimension. */ public void intersect(final Envelope envelope) throws MismatchedDimensionException { final int dim = ord.length/2; envelope.ensureDimensionMatch(dim); for (int i=0; i max) { // Make an empty envelope (min==max) // while keeping it legal (min<=max). min = max = 0.5*(min+max); } ord[i ] = min; ord[i+dim] = max; } } /** * Returns a new envelope representing the intersection of this * Envelope with the specified Envelope. * * @param envelope The Envelope to intersect with this envelope. * @return The largest envelope contained in both the specified Envelope * and in this Envelope. * @throws MismatchedDimensionException if the specified envelope doesn't * have the expected dimension. * @deprecated Use ((Envelope)clone()).intersect(envelope) instead. */ public Envelope createIntersection(final Envelope envelope) throws MismatchedDimensionException { final int dim = ord.length/2; envelope.ensureDimensionMatch(dim); final Envelope dest = new Envelope(dim); for (int i=0; i max) { // Make an empty envelope (min==max) // while keeping it legal (min<=max). min = max = 0.5*(min+max); } dest.ord[i ]=min; dest.ord[i+dim]=max; } return dest; } /** * Returns a new envelope that encompass only some dimensions of this envelope. * This method copy this envelope's ordinates into a new envelope, beginning at * dimension lower and extending to dimension upper-1. * Thus the dimension of the subenvelope is upper-lower. * * @param lower The first dimension to copy, inclusive. * @param upper The last dimension to copy, exclusive. * @return The subenvelope. * @throws IndexOutOfBoundsException if an index is out of bounds. */ public Envelope getSubEnvelope(final int lower, final int upper) { final int curDim = ord.length/2; final int newDim = upper-lower; if (lower<0 || lower>curDim) { throw new IndexOutOfBoundsException(Errors.format( ErrorKeys.ILLEGAL_ARGUMENT_$2, "lower", new Integer(lower))); } if (newDim<0 || upper>curDim) { throw new IndexOutOfBoundsException(Errors.format( ErrorKeys.ILLEGAL_ARGUMENT_$2, "upper", new Integer(upper))); } final Envelope envelope = new Envelope(newDim); System.arraycopy(ord, lower, envelope.ord, 0, newDim); System.arraycopy(ord, lower+curDim, envelope.ord, newDim, newDim); return envelope; } /** * Returns a new envelope with the same values than this envelope minus the * specified range of dimensions. * * @param lower The first dimension to omit, inclusive. * @param upper The last dimension to omit, exclusive. * @return The subenvelope. * @throws IndexOutOfBoundsException if an index is out of bounds. */ public Envelope getReducedEnvelope(final int lower, final int upper) { final int curDim = ord.length/2; final int rmvDim = upper-lower; if (lower<0 || lower>curDim) { throw new IndexOutOfBoundsException(Errors.format( ErrorKeys.ILLEGAL_ARGUMENT_$2, "lower", new Integer(lower))); } if (rmvDim<0 || upper>curDim) { throw new IndexOutOfBoundsException(Errors.format( ErrorKeys.ILLEGAL_ARGUMENT_$2, "upper", new Integer(upper))); } final Envelope envelope = new Envelope(curDim - rmvDim); System.arraycopy(ord, 0, envelope.ord, 0, lower); System.arraycopy(ord, lower, envelope.ord, upper, curDim-upper); return envelope; } /** * Returns a {@link Rectangle2D} with the same bounds as this Envelope. * This is a convenience method for interoperability with Java2D. * * @throws IllegalStateException if this envelope is not two-dimensional. */ public Rectangle2D toRectangle2D() throws IllegalStateException { if (ord.length == 4) { return XRectangle2D.createFromExtremums(ord[0], ord[1], ord[2], ord[3]); } else { throw new IllegalStateException(Errors.format( ErrorKeys.NOT_TWO_DIMENSIONAL_$1, new Integer(getDimension()))); } } /** * Returns a hash value for this envelope. * This value need not remain consistent between * different implementations of the same class. */ public int hashCode() { return CoordinatePoint.hashCode(ord); } /** * Compares the specified object with * this envelope for equality. */ public boolean equals(final Object object) { if (object instanceof Envelope) { final Envelope that = (Envelope) object; return Arrays.equals(this.ord, that.ord); } return false; } /** * Returns a deep copy of this envelope. */ public Object clone() { return new Envelope(this); } /** * Returns a string representation of this envelope. * The returned string is implementation dependent. * It is usually provided for debugging purposes. */ public String toString() { return CoordinatePoint.toString(this, ord); } /** * Mimic a GeoAPI interface as a legacy implementation. This method is provided * as a temporary bridge for using new CRS object with J2D-Renderer for example. */ public static Envelope fromGeoAPI(final org.opengis.spatialschema.geometry.Envelope envelope) { if (envelope instanceof Envelope) { return (Envelope) envelope; } return new Envelope(envelope.getLowerCorner().getCoordinates(), envelope.getUpperCorner().getCoordinates()); } public org.opengis.referencing.crs.CoordinateReferenceSystem getCoordinateReferenceSystem() { return null; } }