/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.geometry;

import java.util.Objects;
import java.awt.geom.Rectangle2D;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.geometry.MismatchedReferenceSystemException;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.cs.AxisDirection;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.Emptiable;

import static java.lang.Double.NaN;
import static java.lang.Double.isNaN;
import static java.lang.Double.doubleToLongBits;
import static org.apache.sis.math.MathFunctions.isSameSign;
import static org.apache.sis.math.MathFunctions.isPositive;
import static org.apache.sis.math.MathFunctions.isNegative;
import static org.apache.sis.math.MathFunctions.isNegativeZero;
import static org.apache.sis.util.ArgumentChecks.ensureDimensionMatches;
import static org.apache.sis.internal.referencing.Formulas.isPoleToPole;

// Following imports are needed because we can't extend AbstractEnvelope.
// We want to write this class as if it was an AbstractEnvelope subclass.
import static org.apache.sis.geometry.AbstractEnvelope.getAxis;
import static org.apache.sis.geometry.AbstractEnvelope.getCommonCRS;
import static org.apache.sis.geometry.AbstractEnvelope.fixSpan;
import static org.apache.sis.geometry.AbstractEnvelope.fixMedian;
import static org.apache.sis.geometry.AbstractEnvelope.isWrapAround;
import static org.apache.sis.geometry.AbstractEnvelope.isNegativeUnsafe;


/**
 * A two-dimensional envelope on top of Java2D rectangle.
 * This implementation is provided for inter-operability between Java2D and GeoAPI.
 *
 * <p>This class inherits {@linkplain #x x} and {@linkplain #y y} fields.
 * But despite their names, they don't need to be oriented toward {@linkplain AxisDirection#EAST East} and
 * {@linkplain AxisDirection#NORTH North} respectively. The (<var>x</var>,<var>y</var>) axis can have any
 * direction and should be understood as <cite>coordinate 0</cite> and <cite>coordinate 1</cite> values instead.
 * This is not specific to this implementation; in Java2D too, the visual axis orientation depend
 * on the {@linkplain java.awt.Graphics2D#getTransform() affine transform in the graphics context}.</p>
 *
 * <h2>Spanning the anti-meridian of a Geographic CRS</h2>
 * The <cite>Web Coverage Service</cite> (WCS) specification authorizes (with special treatment)
 * cases where <var>upper</var> &lt; <var>lower</var> at least in the longitude case. They are
 * envelopes spanning the anti-meridian, like the red box below (the green box is the usual case).
 * For {@code Envelope2D} objects, they are rectangle with negative {@linkplain #width width} or
 * {@linkplain #height height} field values. The default implementation of methods listed in the
 * right column can handle such cases.
 *
 * <div class="horizontal-flow">
 * <div>
 *   <img style="vertical-align: middle" src="doc-files/AntiMeridian.png" alt="Envelope spannning the anti-meridian">
 * </div><div>
 * Supported methods:
 * <ul>
 *   <li>{@link #getMinimum(int)}</li>
 *   <li>{@link #getMaximum(int)}</li>
 *   <li>{@link #getSpan(int)}</li>
 *   <li>{@link #getMedian(int)}</li>
 *   <li>{@link #isEmpty()}</li>
 *   <li>{@link #toRectangles()}</li>
 *   <li>{@link #contains(double,double)}</li>
 *   <li>{@link #contains(Rectangle2D)} and its variant receiving {@code double} arguments</li>
 *   <li>{@link #intersects(Rectangle2D)} and its variant receiving {@code double} arguments</li>
 *   <li>{@link #createIntersection(Rectangle2D)}</li>
 *   <li>{@link #createUnion(Rectangle2D)}</li>
 *   <li>{@link #add(Rectangle2D)}</li>
 *   <li>{@link #add(double,double)}</li>
 * </ul>
 * </div></div>
 *
 * The {@link #getMinX()}, {@link #getMinY()}, {@link #getMaxX()}, {@link #getMaxY()},
 * {@link #getCenterX()}, {@link #getCenterY()}, {@link #getWidth()} and {@link #getHeight()}
 * methods delegate to the above-cited methods.
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @author  Johann Sorel (Geomatys)
 * @version 0.8
 *
 * @see GeneralEnvelope
 * @see org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox
 *
 * @since 0.3
 * @module
 */
public class Envelope2D extends Rectangle2D.Double implements Envelope, Emptiable, Cloneable {
    /**
     * Serial number for inter-operability with different versions.
     */
    private static final long serialVersionUID = 761232175464415062L;

    /**
     * The number of dimensions in every {@code Envelope2D}.
     */
    private static final int DIMENSION = 2;

    /**
     * An empty array of Java2D rectangles, to be returned by {@link #toRectangles()}
     * when en envelope is empty.
     */
    private static final Rectangle2D.Double[] EMPTY = new Rectangle2D.Double[0];

    /**
     * The coordinate reference system, or {@code null}.
     */
    private CoordinateReferenceSystem crs;

    /**
     * Constructs an initially empty envelope with no CRS.
     */
    public Envelope2D() {
    }

    /**
     * Creates a new envelope from the given bounding box. This constructor can not be public,
     * because the {@code xmax} and {@code ymax} arguments are not the ones usually expected for
     * {@link Rectangle2D} objects (the standard arguments are {@code width} and {@code height}).
     * Making this constructor public would probably be a too high risk of confusion.
     *
     * <p>This constructor is needed because the other constructors (expecting envelopes or other
     * rectangles) can not query directly the {@link Envelope#getSpan(int)} or equivalent methods,
     * because the return value is not the one expected by this class when the envelope spans the
     * anti-meridian.</p>
     */
    private Envelope2D(final double xmin, final double ymin, final double xmax, final double ymax) {
        super(xmin, ymin, xmax - xmin, ymax - ymin);
    }

    /**
     * Creates a new envelope from the given positions and CRS.
     * It is the caller responsibility to check the validity of the given CRS.
     *
     * @see #Envelope2D(DirectPosition, DirectPosition)
     */
    private Envelope2D(final CoordinateReferenceSystem crs,
                       final DirectPosition lowerCorner,
                       final DirectPosition upperCorner)
    {
        /*
         * JDK constraint: The call to ensureDimensionMatch(…) should have been first if Sun/Oracle
         * fixed RFE #4093999 (Relax constraint on placement of this()/super() call in constructors).
         */
        this(lowerCorner.getOrdinate(0), lowerCorner.getOrdinate(1),
             upperCorner.getOrdinate(0), upperCorner.getOrdinate(1));
        ensureDimensionMatches("crs", DIMENSION, crs);
        this.crs = crs;
    }

    /**
     * Constructs a two-dimensional envelope defined by the specified coordinates.
     * The {@code lowerCorner} and {@code upperCorner} arguments are not necessarily
     * the minimal and maximal values respectively.
     * See the class javadoc about anti-meridian spanning for more details.
     *
     * @param  lowerCorner  the fist position.
     * @param  upperCorner  the second position.
     * @throws MismatchedReferenceSystemException if the two positions don't use the same CRS.
     * @throws MismatchedDimensionException if the two positions are not two-dimensional.
     */
    public Envelope2D(final DirectPosition lowerCorner, final DirectPosition upperCorner)
            throws MismatchedReferenceSystemException, MismatchedDimensionException
    {
        // The call to getCommonCRS(…) performs a check against null values.
        this(getCommonCRS(lowerCorner, upperCorner), lowerCorner, upperCorner);
    }

    /**
     * Constructs a two-dimensional envelope defined by an other {@link Envelope}.
     *
     * @param  envelope  the envelope to copy (can not be {@code null}).
     * @throws MismatchedDimensionException if the given envelope is not two-dimensional.
     */
    public Envelope2D(final Envelope envelope) throws MismatchedDimensionException {
        this(envelope.getCoordinateReferenceSystem(), envelope.getLowerCorner(), envelope.getUpperCorner());
    }

    /**
     * Constructs a new envelope with the same data than the specified geographic bounding box.
     * The coordinate reference system is set to the
     * {@linkplain org.apache.sis.referencing.CommonCRS#defaultGeographic() default geographic CRS}.
     * Axis order is (<var>longitude</var>, <var>latitude</var>).
     *
     * @param box The bounding box to copy (can not be {@code null}).
     */
    public Envelope2D(final GeographicBoundingBox box) {
        this(box.getWestBoundLongitude(),
             box.getSouthBoundLatitude(),
             box.getEastBoundLongitude(),
             box.getNorthBoundLatitude());
        crs = CommonCRS.defaultGeographic();
        if (Boolean.FALSE.equals(box.getInclusion())) {
            x += width;
            width = -width;
            if (!isPoleToPole(y, y+height)) {
                y += height;
                height = -height;
            }
        }
    }

    /**
     * Constructs two-dimensional envelope defined by an other {@link Rectangle2D}.
     * If the given rectangle has negative width or height, they will be interpreted
     * as an envelope spanning the anti-meridian.
     *
     * @param crs   the coordinate reference system, or {@code null}.
     * @param rect  the rectangle to copy (can not be {@code null}).
     * @throws MismatchedDimensionException if the given CRS is not two-dimensional.
     */
    public Envelope2D(final CoordinateReferenceSystem crs, final Rectangle2D rect)
            throws MismatchedDimensionException
    {
        super(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());     // Really 'super', not 'this'.
        ensureDimensionMatches("crs", DIMENSION, crs);
        this.crs = crs;
    }

    /**
     * Constructs two-dimensional envelope defined by the specified coordinates. Despite
     * their name, the (<var>x</var>,<var>y</var>) coordinates don't need to be oriented
     * toward ({@linkplain AxisDirection#EAST East}, {@linkplain AxisDirection#NORTH North}).
     * Those parameter names simply match the {@linkplain #x x} and {@linkplain #y y} fields.
     * The actual axis orientations are determined by the specified CRS.
     * See the <a href="#skip-navbar_top">class javadoc</a> for details.
     *
     * @param  crs     the coordinate reference system, or {@code null}.
     * @param  x       the <var>x</var> minimal value.
     * @param  y       the <var>y</var> minimal value.
     * @param  width   the envelope width. May be negative for envelope spanning the anti-meridian.
     * @param  height  the envelope height. May be negative for envelope spanning the anti-meridian.
     * @throws MismatchedDimensionException if the given CRS is not two-dimensional.
     */
    public Envelope2D(final CoordinateReferenceSystem crs, final double x, final double y,
            final double width, final double height) throws MismatchedDimensionException
    {
        super(x, y, width, height);                             // Really 'super', not 'this'.
        ensureDimensionMatches("crs", DIMENSION, crs);
        this.crs = crs;
    }

    /**
     * Returns the coordinate reference system in which the coordinates are given.
     *
     * @return the coordinate reference system, or {@code null}.
     */
    @Override
    public final CoordinateReferenceSystem getCoordinateReferenceSystem() {
        return crs;
    }

    /**
     * Sets the coordinate reference system in which the coordinate are given.
     * This method <strong>does not</strong> reproject the envelope.
     * If the envelope coordinates need to be transformed to the new CRS, consider using
     * {@link Envelopes#transform(Envelope, CoordinateReferenceSystem)} instead.
     *
     * @param  crs  the new coordinate reference system, or {@code null}.
     */
    public void setCoordinateReferenceSystem(final CoordinateReferenceSystem crs) {
        ensureDimensionMatches("crs", DIMENSION, crs);
        this.crs = crs;
    }

    /**
     * Sets this envelope to the given rectangle. If the given rectangle is also an instance of {@link Envelope}
     * (typically as another {@code Envelope2D}) and has a non-null Coordinate Reference System (CRS), then the
     * CRS of this envelope will be set to the CRS of the given envelope.
     *
     * @param rect  the rectangle to copy coordinates from.
     *
     * @since 0.8
     */
    @Override
    public void setRect(final Rectangle2D rect) {
        if (rect == this) {
            return;         // Optimization for methods chaining like env.setRect(Shapes.transform(…, env))
        }
        if (rect instanceof Envelope) {
            final CoordinateReferenceSystem envelopeCRS = ((Envelope) rect).getCoordinateReferenceSystem();
            if (envelopeCRS != null) {
                setCoordinateReferenceSystem(envelopeCRS);
            }
        }
        super.setRect(rect);
    }

    /**
     * Returns the number of dimensions, which is always 2.
     *
     * @return always 2 for bi-dimensional objects.
     */
    @Override
    public final int getDimension() {
        return DIMENSION;
    }

    /**
     * The limits in the direction of decreasing coordinate values for the two dimensions.
     * This is typically a coordinate position consisting of the minimal coordinates for
     * the two dimensions for all points within the {@code Envelope}.
     *
     * <p>The object returned by this method is a copy. Change in the returned position
     * will not affect this envelope, and conversely.</p>
     *
     * <div class="note"><b>Note:</b>
     * The <cite>Web Coverage Service</cite> (WCS) 1.1 specification uses an extended interpretation of the
     * bounding box definition. In a WCS 1.1 data structure, the lower corner defines the edges region in the
     * directions of <em>decreasing</em> coordinate values in the envelope CRS. This is usually the algebraic
     * minimum coordinates, but not always. For example, an envelope spanning the anti-meridian could have a
     * lower corner longitude greater than the upper corner longitude. Such extended interpretation applies
     * mostly to axes having {@code WRAPAROUND} range meaning.</div>
     *
     * @return a copy of the lower corner, typically (but not necessarily) containing minimal coordinate values.
     */
    @Override
    public DirectPosition2D getLowerCorner() {
        return new DirectPosition2D(crs, x, y);
    }

    /**
     * The limits in the direction of increasing coordinate values for the two dimensions.
     * This is typically a coordinate position consisting of the maximal coordinates for
     * the two dimensions for all points within the {@code Envelope}.
     *
     * <p>The object returned by this method is a copy. Change in the returned position
     * will not affect this envelope, and conversely.</p>
     *
     * <div class="note"><b>Note:</b>
     * The <cite>Web Coverage Service</cite> (WCS) 1.1 specification uses an extended interpretation of the
     * bounding box definition. In a WCS 1.1 data structure, the upper corner defines the edges region in the
     * directions of <em>increasing</em> coordinate values in the envelope CRS. This is usually the algebraic
     * maximum coordinates, but not always. For example, an envelope spanning the anti-meridian could have an
     * upper corner longitude less than the lower corner longitude. Such extended interpretation applies
     * mostly to axes having {@code WRAPAROUND} range meaning.</div>
     *
     * @return a copy of the upper corner, typically (but not necessarily) containing maximal coordinate values.
     */
    @Override
    public DirectPosition2D getUpperCorner() {
        return new DirectPosition2D(crs, x+width, y+height);
    }

    /**
     * Creates an exception for an index out of bounds.
     */
    private static IndexOutOfBoundsException indexOutOfBounds(final int dimension) {
        return new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, dimension));
    }

    /**
     * Returns the minimal coordinate along the specified dimension. This method handles
     * anti-meridian spanning as documented in the {@link AbstractEnvelope#getMinimum(int)}
     * method.
     *
     * @param  dimension  the dimension to query.
     * @return the minimal coordinate value along the given dimension.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     */
    @Override
    public double getMinimum(final int dimension) throws IndexOutOfBoundsException {
        final double value, span;
        switch (dimension) {
            case 0:  value=x; span=width;  break;
            case 1:  value=y; span=height; break;
            default: throw indexOutOfBounds(dimension);
        }
        if (isNegative(span)) {                                         // Special handling for -0.0
            final CoordinateSystemAxis axis = getAxis(crs, dimension);
            return isWrapAround(axis) ? axis.getMinimumValue() : NaN;
        }
        return value;
    }

    /**
     * Returns the maximal coordinate along the specified dimension. This method handles
     * anti-meridian spanning as documented in the {@link AbstractEnvelope#getMaximum(int)}
     * method.
     *
     * @param  dimension  the dimension to query.
     * @return the maximal coordinate value along the given dimension.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     */
    @Override
    public double getMaximum(final int dimension) throws IndexOutOfBoundsException {
        final double value, span;
        switch (dimension) {
            case 0:  value=x; span=width;  break;
            case 1:  value=y; span=height; break;
            default: throw indexOutOfBounds(dimension);
        }
        if (isNegative(span)) {                                         // Special handling for -0.0
            final CoordinateSystemAxis axis = getAxis(crs, dimension);
            return isWrapAround(axis) ? axis.getMaximumValue() : NaN;
        }
        return value + span;
    }

    /**
     * Returns the median coordinate along the specified dimension. This method handles
     * anti-meridian spanning as documented in the {@link AbstractEnvelope#getMedian(int)}
     * method.
     *
     * @param  dimension  the dimension to query.
     * @return the mid coordinate value along the given dimension.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     */
    @Override
    public double getMedian(final int dimension) throws IndexOutOfBoundsException {
        double value, span;
        switch (dimension) {
            case 0:  value=x; span=width;  break;
            case 1:  value=y; span=height; break;
            default: throw indexOutOfBounds(dimension);
        }
        value += 0.5*span;
        if (isNegative(span)) {                                         // Special handling for -0.0
            value = fixMedian(getAxis(crs, dimension), value);
        }
        return value;
    }

    /**
     * Returns the envelope span along the specified dimension. This method handles anti-meridian
     * spanning as documented in the {@link AbstractEnvelope#getSpan(int)} method.
     *
     * @param  dimension  the dimension to query.
     * @return the rectangle width or height, depending the given dimension.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
      */
    @Override
    public double getSpan(final int dimension) throws IndexOutOfBoundsException {
        double span;
        switch (dimension) {
            case 0:  span=width;  break;
            case 1:  span=height; break;
            default: throw indexOutOfBounds(dimension);
        }
        if (isNegative(span)) {                                         // Special handling for -0.0
            span = fixSpan(getAxis(crs, dimension), span);
        }
        return span;
    }

    // Do not override getX() and getY() - their default implementations is okay.

    /**
     * Returns the {@linkplain #getMinimum(int) minimal} coordinate value for dimension 0.
     * The default implementation invokes <code>{@linkplain #getMinimum(int) getMinimum}(0)</code>.
     * The result is the standard {@link Rectangle2D} value (namely {@linkplain #x x})
     * only if the envelope is not spanning the anti-meridian.
     *
     * @return the minimal coordinate value for dimension 0.
     */
    @Override
    public double getMinX() {
        return getMinimum(0);
    }

    /**
     * Returns the {@linkplain #getMinimum(int) minimal} coordinate value for dimension 1.
     * The default implementation invokes <code>{@linkplain #getMinimum(int) getMinimum}(1)</code>.
     * The result is the standard {@link Rectangle2D} value (namely {@linkplain #y y})
     * only if the envelope is not spanning the anti-meridian.
     *
     * @return the minimal coordinate value for dimension 1.
     */
    @Override
    public double getMinY() {
        return getMinimum(1);
    }

    /**
     * Returns the {@linkplain #getMaximum(int) maximal} coordinate value for dimension 0.
     * The default implementation invokes <code>{@linkplain #getMaximum(int) getMinimum}(0)</code>.
     * The result is the standard {@link Rectangle2D} value (namely {@linkplain #x x} + {@linkplain #width width})
     * only if the envelope is not spanning the anti-meridian.
     *
     * @return the maximal coordinate value for dimension 0.
     */
    @Override
    public double getMaxX() {
        return getMaximum(0);
    }

    /**
     * Returns the {@linkplain #getMaximum(int) maximal} coordinate value for dimension 1.
     * The default implementation invokes <code>{@linkplain #getMaximum(int) getMinimum}(1)</code>.
     * The result is the standard {@link Rectangle2D} value (namely {@linkplain #y y} + {@linkplain #height height})
     * only if the envelope is not spanning the anti-meridian.
     *
     * @return the maximal coordinate value for dimension 1.
     */
    @Override
    public double getMaxY() {
        return getMaximum(1);
    }

    /**
     * Returns the {@linkplain #getMedian(int) median} coordinate value for dimension 0.
     * The default implementation invokes <code>{@linkplain #getMedian(int) getMedian}(0)</code>.
     * The result is the standard {@link Rectangle2D} value (namely {@linkplain #x x} + {@linkplain #width width}/2)
     * only if the envelope is not spanning the anti-meridian.
     *
     * @return the median coordinate value for dimension 0.
     */
    @Override
    public double getCenterX() {
        return getMedian(0);
    }

    /**
     * Returns the {@linkplain #getMedian(int) median} coordinate value for dimension 1.
     * The default implementation invokes <code>{@linkplain #getMedian(int) getMedian}(1)</code>.
     * The result is the standard {@link Rectangle2D} value (namely {@linkplain #y y} + {@linkplain #height height}/2)
     * only if the envelope is not spanning the anti-meridian.
     *
     * @return the median coordinate value for dimension 1.
     */
    @Override
    public double getCenterY() {
        return getMedian(1);
    }

    /**
     * Returns the {@linkplain #getSpan(int) span} for dimension 0.
     * The default implementation invokes <code>{@linkplain #getSpan(int) getSpan}(0)</code>.
     * The result is the standard {@link Rectangle2D} value (namely {@linkplain #width width})
     * only if the envelope is not spanning the anti-meridian.
     *
     * @return the span for dimension 0.
     */
    @Override
    public double getWidth() {
        return getSpan(0);
    }

    /**
     * Returns the {@linkplain #getSpan(int) span} for dimension 1.
     * The default implementation invokes <code>{@linkplain #getSpan(int) getSpan}(1)</code>.
     * The result is the standard {@link Rectangle2D} value (namely {@linkplain #height height})
     * only if the envelope is not spanning the anti-meridian.
     *
     * @return the span for dimension 1.
     */
    @Override
    public double getHeight() {
        return getSpan(1);
    }

    /**
     * Determines whether the envelope is empty. A negative {@linkplain #width} or
     * (@linkplain #height} is considered as a non-empty area if the corresponding
     * axis has the {@linkplain org.opengis.referencing.cs.RangeMeaning#WRAPAROUND
     * wraparound} range meaning.
     *
     * <p>Note that if the {@linkplain #width} or {@linkplain #height} value is
     * {@link java.lang.Double#NaN NaN}, then the envelope is considered empty.
     * This is different than the default {@link java.awt.geom.Rectangle2D.Double#isEmpty()}
     * implementation, which doesn't check for {@code NaN} values.</p>
     *
     * @return {@code true} if this envelope is empty.
     */
    @Override
    public boolean isEmpty() {
        return !((width  > 0 || (isNegative(width)  && isWrapAround(crs, 0)))
              && (height > 0 || (isNegative(height) && isWrapAround(crs, 1))));
    }

    /**
     * Returns this envelope as non-empty Java2D rectangle objects. This method returns an array of length 0, 1,
     * 2 or 4 depending on whether the envelope crosses the anti-meridian or the limit of any other axis having
     * {@linkplain org.opengis.referencing.cs.RangeMeaning#WRAPAROUND wraparound} range meaning.
     * More specifically:
     *
     * <ul>
     *   <li>If this envelope {@linkplain #isEmpty() is empty}, then this method returns an empty array.</li>
     *   <li>If this envelope does not have any wraparound behavior, then this method returns a copy
     *       of this envelope as an instance of {@code Rectangle2D.Double} in an array of length 1.</li>
     *   <li>If this envelope crosses the <cite>anti-meridian</cite> (a.k.a. <cite>date line</cite>)
     *       then this method represents this envelope as two separated rectangles.
     *   <li>While uncommon, the envelope could theoretically crosses the limit of other axis having
     *       wraparound range meaning. If wraparound occur along the two axes, then this method
     *       represents this envelope as four separated rectangles.
     * </ul>
     *
     * <div class="note"><b>API note:</b>
     * The return type is the {@code Rectangle2D.Double} implementation class rather than the {@code Rectangle2D}
     * abstract class because the {@code Envelope2D} class hierarchy already exposes this implementation choice.</div>
     *
     * @return a representation of this envelope as an array of non-empty Java2D rectangles.
     *         The array never contains {@code this}.
     *
     * @see GeneralEnvelope#toSimpleEnvelopes()
     *
     * @since 0.4
     */
    @SuppressWarnings("ReturnOfCollectionOrArrayField")
    public Rectangle2D.Double[] toRectangles() {
        int isWrapAround = 0;                   // A bitmask of the dimensions having a "wrap around" behavior.
        for (int i=0; i!=DIMENSION; i++) {
            final double span = (i == 0) ? width : height;
            if (!(span > 0)) {                                                      // Use '!' for catching NaN.
                if (!isNegative(span) || !isWrapAround(crs, i)) {
                    return EMPTY;
                }
                isWrapAround |= (1 << i);
            }
        }
        /*
         * The number of rectangles is 2ⁿ where n is the number of wraparound found.
         */
        final Rectangle2D.Double[] rect = new Rectangle2D.Double[1 << Integer.bitCount(isWrapAround)];
        for (int i=0; i<rect.length; i++) {
            rect[i] = new Rectangle2D.Double(x, y, width, height);
        }
        if ((isWrapAround & 1) != 0) {
            /*
             *  (x+width)   (x)
             *          ↓   ↓
             *    ──────┐   ┌───────
             *    …next │   │ start…
             *    ──────┘   └───────
             */
            final CoordinateSystemAxis axis = getAxis(crs, 0);
            final Rectangle2D.Double start = rect[0];
            final Rectangle2D.Double next  = rect[1];
            start.width = axis.getMaximumValue() - x;
            next.x      = axis.getMinimumValue();
            next.width += x - next.x;
        }
        if ((isWrapAround & 2) != 0) {
            /*
             *              │   ⋮   │
             *              │ start │
             * (y)        → └───────┘
             * (y+height) → ┌───────┐
             *              │ next  │
             *              │   ⋮   │
             */
            final CoordinateSystemAxis axis = getAxis(crs, 1);
            final Rectangle2D.Double start = rect[0];
            final Rectangle2D.Double next  = rect[isWrapAround - 1];    // == 1 if y is the only wraparound axis, or 2 otherwise.
            start.height = axis.getMaximumValue() - y;
            next.y       = axis.getMinimumValue();
            next.height += y - next.y;
        }
        if (isWrapAround == 3) {
            /*
             * If there is a wraparound along both axes, copy the values.
             * The (x) and (y) labels indicate which values to copy.
             *
             *      (y) R1 │   │ R0
             *    ─────────┘   └─────────
             *    ─────────┐   ┌─────────
             *    (x,y) R3 │   │ R2 (x)
             */
            rect[1].height = rect[0].height;
            rect[2].width  = rect[0].width;
            rect[3].x      = rect[1].x;
            rect[3].width  = rect[1].width;
            rect[3].y      = rect[2].y;
            rect[3].height = rect[2].height;
        }
        return rect;
    }

    /**
     * Tests if a specified coordinate is inside the boundary of this envelope. If it least one
     * of the given coordinate value is {@link java.lang.Double#NaN NaN}, then this method returns
     * {@code false}.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method supports anti-meridian spanning in the same way than
     * {@link AbstractEnvelope#contains(DirectPosition)}.
     *
     * @param  px  the first coordinate value of the point to text.
     * @param  py  the second coordinate value of the point to text.
     * @return {@code true} if the specified coordinate is inside the boundary of this envelope;
     *         {@code false} otherwise.
     */
    @Override
    public boolean contains(final double px, final double py) {
        boolean c1 = (px >= x);
        boolean c2 = (px <= x + width);
        // See AbstractEnvelope.contains(DirectPosition) for explanation.
        if ((c1 & c2) || ((c1 | c2) && isNegative(width))) {
            // Same check, but for y axis.
            c1 = (py >= y);
            c2 = (py <= y + height);
            return (c1 & c2) || ((c1 | c2) && isNegative(height));
        }
        return false;
    }

    /**
     * Returns {@code true} if this envelope completely encloses the specified rectangle. If this
     * envelope or the given rectangle have at least one {@link java.lang.Double#NaN NaN} value,
     * then this method returns {@code false}.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method supports anti-meridian spanning in the same way than
     * {@link AbstractEnvelope#contains(Envelope)}.
     *
     * @param  rect  the rectangle to test for inclusion.
     * @return {@code true} if this envelope completely encloses the specified rectangle.
     */
    @Override
    public boolean contains(final Rectangle2D rect) {
        if (rect instanceof Envelope2D) {
            // Need to bypass the overriden getWidth()/getHeight().
            final Envelope2D env = (Envelope2D) rect;
            return contains(env.x, env.y, env.width, env.height);
        }
        return super.contains(rect);
    }

    /**
     * Returns {@code true} if this envelope completely encloses the specified rectangle. If this
     * envelope or the given rectangle have at least one {@link java.lang.Double#NaN NaN} value,
     * then this method returns {@code false}.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method supports anti-meridian spanning in the same way than
     * {@link AbstractEnvelope#contains(Envelope)}.
     *
     * @param  rx  the <var>x</var> coordinate of the lower corner of the rectangle to test for inclusion.
     * @param  ry  the <var>y</var> coordinate of the lower corner of the rectangle to test for inclusion.
     * @param  rw  the width of the rectangle to test for inclusion. May be negative if the rectangle spans the anti-meridian.
     * @param  rh  the height of the rectangle to test for inclusion. May be negative.
     * @return {@code true} if this envelope completely encloses the specified one.
     */
    @Override
    public boolean contains(final double rx, final double ry, final double rw, final double rh) {
        for (int i=0; i!=DIMENSION; i++) {
            final double min0, min1, span0, span1;
            if (i == 0) {
                min0 =  x;  span0 = width;
                min1 = rx;  span1 = rw;
            } else {
                min0 =  y;  span0 = height;
                min1 = ry;  span1 = rh;
            }
            /*
             * See AbstractEnvelope.contains(Envelope) for an illustration of the algorithm applied here.
             */
            final boolean minCondition = (min1 >= min0);
            final boolean maxCondition = (min1 + span1 <= min0 + span0);
            if (minCondition & maxCondition) {
                if (!isNegativeUnsafe(span1) || isNegativeUnsafe(span0)) {
                    continue;
                }
                if (span0 >= AbstractEnvelope.getSpan(getAxis(crs, i))) {
                    continue;
                }
            } else if (minCondition != maxCondition) {
                if (isNegative(span0) && isPositive(span1)) {
                    continue;
                }
            } else if (isNegativeZero(span0)) {
                continue;
            }
            return false;
        }
        return true;
    }

    /**
     * Returns {@code true} if this envelope intersects the specified envelope. If this envelope
     * or the given rectangle have at least one {@link java.lang.Double#NaN NaN} value, then this
     * method returns {@code false}.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method supports anti-meridian spanning in the same way than
     * {@link AbstractEnvelope#intersects(Envelope)}.
     *
     * @param  rect  the rectangle to test for intersection.
     * @return {@code true} if this envelope intersects the specified rectangle.
     */
    @Override
    public boolean intersects(final Rectangle2D rect) {
        if (rect instanceof Envelope2D) {
            // Need to bypass the overriden getWidth()/getHeight().
            final Envelope2D env = (Envelope2D) rect;
            return intersects(env.x, env.y, env.width, env.height);
        }
        return super.intersects(rect);
    }

    /**
     * Returns {@code true} if this envelope intersects the specified envelope. If this envelope
     * or the given rectangle have at least one {@link java.lang.Double#NaN NaN} value, then this
     * method returns {@code false}.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method supports anti-meridian spanning in the same way than
     * {@link AbstractEnvelope#intersects(Envelope)}.
     *
     * @param  rx  the <var>x</var> coordinate of the lower corner of the rectangle to test for intersection.
     * @param  ry  the <var>y</var> coordinate of the lower corner of the rectangle to test for intersection.
     * @param  rw  the width of the rectangle to test for inclusion. May be negative if the rectangle spans the anti-meridian.
     * @param  rh  the height of the rectangle to test for inclusion. May be negative.
     * @return {@code true} if this envelope intersects the specified rectangle.
     */
    @Override
    public boolean intersects(final double rx, final double ry, final double rw, final double rh) {
        for (int i=0; i!=DIMENSION; i++) {
            final double min0, min1, span0, span1;
            if (i == 0) {
                min0 =  x;  span0 = width;
                min1 = rx;  span1 = rw;
            } else {
                min0 =  y;  span0 = height;
                min1 = ry;  span1 = rh;
            }
            /*
             * See AbstractEnvelope.intersects(Envelope) for an illustration of the algorithm applied here.
             * We use < operator, not <=, for consistency with the standard "intersects" definition.
             */
            final boolean minCondition = (min1 < min0 + span0);
            final boolean maxCondition = (min1 + span1 > min0);
            if (maxCondition & minCondition) {
                continue;
            }
            final boolean sp0 = isNegative(span0);
            final boolean sp1 = isNegative(span1);
            if (sp0 | sp1) {
                if ((sp0 & sp1) | (maxCondition | minCondition)) {
                    continue;
                }
            }
            return false;
        }
        return true;
    }

    /**
     * Returns the intersection of this envelope with the specified rectangle. If this envelope
     * or the given rectangle have at least one {@link java.lang.Double#NaN NaN} values, then this
     * method returns an {@linkplain #isEmpty() empty} envelope.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method supports anti-meridian spanning in the same way than
     * {@link GeneralEnvelope#intersect(Envelope)}.
     *
     * @param  rect  the rectangle to be intersected with this envelope.
     * @return the intersection of the given rectangle with this envelope.
     */
    @Override
    public Envelope2D createIntersection(final Rectangle2D rect) {
        final Envelope2D env = (rect instanceof Envelope2D) ? (Envelope2D) rect : null;
        final Envelope2D inter = new Envelope2D(crs, NaN, NaN, NaN, NaN);
        for (int i=0; i!=DIMENSION; i++) {
            final double min0, min1, span0, span1;
            if (i == 0) {
                min0  = x;
                span0 = width;
                min1  = rect.getX();
                span1 = (env != null) ? env.width : rect.getWidth();
            } else {
                min0  = y;
                span0 = height;
                min1  = rect.getY();
                span1 = (env != null) ? env.height : rect.getHeight();
            }
            /*
             * The purpose for (min != 0) test before addition is to preserve the sign of zero.
             * In the [0 … -0] range, the span is -0. But computing max = 0 + -0 result in +0,
             * while we need max = -0 in this case.
             */
            final double max0 = (min0 != 0) ? min0 + span0 : span0;
            final double max1 = (min1 != 0) ? min1 + span1 : span1;
            double min = Math.max(min0, min1);
            double max = Math.min(max0, max1);
            /*
             * See GeneralEnvelope.intersect(Envelope) for an explanation of the algorithm applied below.
             */
            if (isSameSign(span0, span1)) {                 // Always 'false' if any value is NaN.
                if ((min1 > max0 || max1 < min0) && !isNegativeUnsafe(span0)) {
                    continue;                               // No intersection: leave coordinate values to NaN
                }
            } else if (isNaN(span0) || isNaN(span1)) {
                continue;                                   // Leave coordinate values to NaN
            } else {
                int intersect = 0;                          // A bitmask of intersections (two bits).
                if (isNegativeUnsafe(span0)) {
                    if (min1 <= max0) {min = min1; intersect  = 1;}
                    if (max1 >= min0) {max = max1; intersect |= 2;}
                } else {
                    if (min0 <= max1) {min = min0; intersect  = 1;}
                    if (max0 >= min1) {max = max0; intersect |= 2;}
                }
                if (intersect == 0 || intersect == 3) {
                    final double csSpan = AbstractEnvelope.getSpan(getAxis(crs, i));
                    if (span1 >= csSpan || isNegativeZero(span1)) {
                        min = min0;
                        max = max0;
                    } else if (span0 >= csSpan || isNegativeZero(span0)) {
                        min = min1;
                        max = max1;
                    } else {
                        continue;                           // Leave coordinate values to NaN
                    }
                }
            }
            inter.setRange(i, min, max);
        }
        assert inter.isEmpty() || (contains(inter) && rect.contains(inter)) : inter;
        return inter;
    }

    /**
     * Returns the union of this envelope with the specified rectangle.
     * The default implementation clones this envelope, then delegates
     * to {@link #add(Rectangle2D)}.
     *
     * @param  rect  the rectangle to add to this envelope.
     * @return the union of the given rectangle with this envelope.
     */
    @Override
    public Envelope2D createUnion(final Rectangle2D rect) {
        final Envelope2D union = clone();
        union.add(rect);
        assert union.isEmpty() || (union.contains(this) && union.contains(rect)) : union;
        return union;
    }

    /**
     * Adds an other rectangle to this rectangle. The resulting rectangle is the union of the
     * two {@code Rectangle} objects.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method supports anti-meridian spanning in the same way than
     * {@link GeneralEnvelope#add(Envelope)}, except if the result is a rectangle expanding to
     * infinities. In the later case, the field values are set to {@code NaN} because infinite
     * values are a little bit problematic in {@link Rectangle2D} objects.
     *
     * @param  rect  the rectangle to add to this envelope.
     */
    @Override
    public void add(final Rectangle2D rect) {
        final Envelope2D env = (rect instanceof Envelope2D) ? (Envelope2D) rect : null;
        for (int i=0; i!=DIMENSION; i++) {
            final double min0, min1, span0, span1;
            if (i == 0) {
                min0  = x;
                span0 = width;
                min1  = rect.getX();
                span1 = (env != null) ? env.width : rect.getWidth();
                x = width = NaN;
            } else {
                min0  = y;
                span0 = height;
                min1  = rect.getY();
                span1 = (env != null) ? env.height : rect.getHeight();
                y = height = NaN;
            }
            final double max0 = min0 + span0;
            final double max1 = min1 + span1;
            double min = Math.min(min0, min1);
            double max = Math.max(max0, max1);
            /*
             * See GeneralEnvelope.add(Envelope) for an explanation of the algorithm applied below.
             * Note that the "continue" statement has reverse meaning: coordinates are left to NaN.
             */
            final boolean sp0 = isNegative(span0);
            final boolean sp1 = isNegative(span1);
            if (sp0 == sp1) {
                if (sp0 && !isNegativeUnsafe(max - min)) {
                    continue;                                   // Leave coordinates to NaN.
                }
            } else if (sp0) {
                if (max1 <= max0 || min1 >= min0) {
                    min = min0;
                    max = max0;
                } else {
                    final double left  = min1 - max0;
                    final double right = min0 - max1;
                    if (!(left > 0 || right > 0)) {
                        continue;                               // Leave coordinates to NaN.
                    }
                    if (left > right) {min = min1; max = max0;}
                    if (right > left) {min = min0; max = max1;}
                }
            } else {
                if (max0 <= max1 || min0 >= min1) {
                    min = min1;
                    max = max1;
                } else {
                    final double left  = min0 - max1;
                    final double right = min1 - max0;
                    if (!(left > 0 || right > 0)) {
                        continue;                               // Leave coordinates to NaN.
                    }
                    if (left > right) {min = min0; max = max1;}
                    if (right > left) {min = min1; max = max0;}
                }
            }
            setRange(i, min, max);
        }
    }

    /**
     * Sets the envelope 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.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     */
    private void setRange(final int dimension, final double minimum, final double maximum)
            throws IndexOutOfBoundsException
    {
        final double span = maximum - minimum;
        switch (dimension) {
            case 0: x = minimum; width  = span; break;
            case 1: y = minimum; height = span; break;
            default: throw indexOutOfBounds(dimension);
        }
    }

    /**
     * Adds a point to this rectangle. The resulting rectangle is the smallest rectangle that
     * contains both the original rectangle and the specified point.
     * <p>
     * After adding a point, a call to {@link #contains(double, double)} with the added point
     * as an argument will return {@code true}, except if one of the point coordinates was
     * {@link java.lang.Double#NaN} in which case the corresponding coordinate has been ignored.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method supports anti-meridian spanning in the same way than
     * {@link GeneralEnvelope#add(DirectPosition)}.
     *
     * @param  px  the first coordinate of the point to add.
     * @param  py  the second coordinate of the point to add.
     */
    @Override
    public void add(final double px, final double py) {
        double off = px - x;
        if (!isNegative(width)) {                           // Standard case, or NaN.
            if (off < 0) {x=px; width -= off;}
            if (off > width)   {width  = off;}
        } else if (off < 0) {
            final double r = width - off;
            if (r < 0) {
                if (r > off) width  = off;
                else {x=px;  width -= off;}
            }
        }
        off = py - y;
        if (!isNegative(height)) {
            if (off < 0) {y=py; height -= off;}
            if (off > height)  {height  = off;}
        } else if (off < 0) {
            final double r = height - off;
            if (r < 0) {
                if (r > off) height  = off;
                else {y=py;  height -= off;}
            }
        }
        assert contains(px, py) || isEmpty() || isNaN(px) || isNaN(py);
    }

    /**
     * Compares the specified object with this envelope for equality. If the given object is not
     * an instance of {@code Envelope2D}, then the two objects are compared as plain rectangles,
     * i.e. the {@linkplain #getCoordinateReferenceSystem() coordinate reference system} of this
     * envelope is ignored.
     *
     * <h4>Note on {@code hashCode()}</h4>
     * This class does not override the {@link #hashCode()} method for consistency with the
     * {@link Rectangle2D#equals(Object)} method, which compare arbitrary {@code Rectangle2D}
     * implementations.
     *
     * @param  object  the object to compare with this envelope.
     * @return {@code true} if the given object is equal to this envelope.
     */
    @Override
    public boolean equals(final Object object) {
        if (object instanceof Envelope2D) {
            final Envelope2D other = (Envelope2D) object;
            return doubleToLongBits(x)      == doubleToLongBits(other.x)      &&
                   doubleToLongBits(y)      == doubleToLongBits(other.y)      &&
                   doubleToLongBits(width)  == doubleToLongBits(other.width)  &&
                   doubleToLongBits(height) == doubleToLongBits(other.height) &&
                   Objects.equals(crs, other.crs);
        } else {
            return super.equals(object);
        }
    }

    /**
     * Returns {@code true} if {@code this} envelope bounds is equal to {@code that} envelope
     * bounds in two specified dimensions. The coordinate reference system is not compared, since
     * it doesn't need to have the same number of dimensions.
     *
     * @param that  the envelope to compare to.
     * @param xDim  the dimension of {@code that} envelope to compare to the <var>x</var> dimension of {@code this} envelope.
     * @param yDim  the dimension of {@code that} envelope to compare to the <var>y</var> dimension of {@code this} envelope.
     * @param eps   a small tolerance number for floating point number comparisons. This value will be scaled
     *              according this envelope {@linkplain #width width} and {@linkplain #height height}.
     * @return {@code true} if the envelope bounds are the same (up to the specified tolerance
     *         level) in the specified dimensions, or {@code false} otherwise.
     */
    public boolean boundsEquals(final Envelope that, final int xDim, final int yDim, double eps) {
        eps *= 0.5*(width + height);
        for (int i=0; i<4; i++) {
            final int dim2D = (i & 1);
            final int dimND = (dim2D == 0) ? xDim : yDim;
            final double value2D, valueND;
            if ((i & 2) == 0) {
                value2D = this.getMinimum(dim2D);
                valueND = that.getMinimum(dimND);
            } else {
                value2D = this.getMaximum(dim2D);
                valueND = that.getMaximum(dimND);
            }
            // Use '!' for catching NaN values.
            if (!(Math.abs(value2D - valueND) <= eps)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns a clone of this envelope.
     *
     * @return a clone of this envelope.
     */
    @Override
    public Envelope2D clone() {
        return (Envelope2D) super.clone();
    }

    /**
     * Formats this envelope as a "{@code BOX}" element.
     * The output is of the form "{@code BOX(}{@linkplain #getLowerCorner()
     * lower corner}{@code ,}{@linkplain #getUpperCorner() upper corner}{@code )}".
     * Example:
     *
     * {@preformat wkt
     *   BOX(-90 -180, 90 180)
     * }
     *
     * @see Envelopes#toString(Envelope)
     */
    @Override
    public String toString() {
        return AbstractEnvelope.toString(this, false);
    }
}
