/*
* 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;
}
}