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

/*
 * Do not add dependency to java.awt.Rectangle2D in this class, because not every platforms
 * support Java2D (e.g. Android),  or applications that do not need it may want to avoid to
 * force installation of the Java2D module (e.g. JavaFX/SWT).
 */
import java.util.Objects;
import java.io.Serializable;
import javax.measure.Unit;
import javax.measure.IncommensurableException;
import javax.xml.bind.annotation.XmlTransient;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.RangeMeaning;
import org.apache.sis.util.Emptiable;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.internal.referencing.WKTUtilities;
import org.apache.sis.math.Vector;

import static java.lang.Double.doubleToLongBits;
import static org.apache.sis.internal.util.Numerics.SIGN_BIT_MASK;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
import static org.apache.sis.util.ArgumentChecks.ensureDimensionMatches;
import static org.apache.sis.util.StringBuilders.trimFractionalPart;
import static org.apache.sis.math.MathFunctions.epsilonEqual;
import static org.apache.sis.math.MathFunctions.isPositive;
import static org.apache.sis.math.MathFunctions.isNegative;
import static org.apache.sis.math.MathFunctions.isNegativeZero;


/**
 * Default implementations of most {@code Envelope} methods, leaving the data storage to subclasses.
 * This base class does not hold any state and does not implement the {@link java.io.Serializable}
 * or {@link Cloneable} interfaces. The internal representation, and the choice to be cloneable or
 * serializable, is left to subclasses.
 *
 * <p>Implementers needs to define at least the following methods:</p>
 * <ul>
 *   <li>{@link #getDimension()}</li>
 *   <li>{@link #getCoordinateReferenceSystem()}</li>
 *   <li>{@link #getLower(int)}</li>
 *   <li>{@link #getUpper(int)}</li>
 * </ul>
 *
 * <p>All other methods, including {@link #toString()}, {@link #equals(Object)} and {@link #hashCode()},
 * are implemented on top of the above four methods.</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 crossing the anti-meridian, like the red box below (the green box is the usual case).
 * 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 #getMedian(int)}</li>
 *   <li>{@link #getSpan(int)}</li>
 *   <li>{@link #toSimpleEnvelopes()}</li>
 *   <li>{@link #contains(DirectPosition)}</li>
 *   <li>{@link #contains(Envelope)}</li>
 *   <li>{@link #intersects(Envelope)}</li>
 * </ul>
 * </div></div>
 *
 * <h2>Choosing the range of longitude values</h2>
 * Geographic CRS typically have longitude values in the [-180 … +180]° range, but the [0 … 360]°
 * range is also occasionally used. Users of this class need to ensure that this envelope CRS is
 * associated to axes having the desired {@linkplain CoordinateSystemAxis#getMinimumValue() minimum}
 * and {@linkplain CoordinateSystemAxis#getMaximumValue() maximum value}.
 *
 * <h2>Note on positive and negative zeros</h2>
 * The IEEE 754 standard defines two different values for positive zero and negative zero.
 * When used with SIS envelopes and keeping in mind the above discussion, those zeros have
 * different meanings:
 *
 * <ul>
 *   <li>The [-0…0]° range is an empty envelope.</li>
 *   <li>The [0…-0]° range makes a full turn around the globe, like the [-180…180]°
 *       range except that the former range spans across the anti-meridian.</li>
 * </ul>
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 1.0
 * @since   0.3
 * @module
 */
@XmlTransient
public abstract class AbstractEnvelope extends FormattableObject implements Envelope, Emptiable {
    /**
     * An empty array of envelopes, to be returned by {@link #toSimpleEnvelopes()}
     * when en envelope is empty.
     */
    private static final Envelope[] EMPTY = new Envelope[0];

    /**
     * Constructs an envelope.
     */
    protected AbstractEnvelope() {
    }

    /**
     * Returns the given envelope as an {@code AbstractEnvelope} instance.
     * If the given envelope is already an instance of {@code AbstractEnvelope},
     * then it is returned unchanged. Otherwise the coordinate values and the CRS
     * of the given envelope are copied in a new envelope.
     *
     * @param  envelope  the envelope to cast, or {@code null}.
     * @return the values of the given envelope as an {@code AbstractEnvelope} instance.
     *
     * @see GeneralEnvelope#castOrCopy(Envelope)
     * @see ImmutableEnvelope#castOrCopy(Envelope)
     */
    public static AbstractEnvelope castOrCopy(final Envelope envelope) {
        if (envelope == null || envelope instanceof AbstractEnvelope) {
            return (AbstractEnvelope) envelope;
        }
        return new GeneralEnvelope(envelope);
    }

    /**
     * Returns {@code true} if at least one of the specified CRS is null, or both CRS are equals.
     * This special processing for {@code null} values is different from the usual contract of an
     * {@code equals} method, but allow to handle the case where the CRS is unknown.
     *
     * <p>Note that in debug mode (to be used in assertions only), the comparisons are actually a
     * bit more relax than just "ignoring metadata", since some rounding errors are tolerated.</p>
     */
    static boolean equalsIgnoreMetadata(final CoordinateReferenceSystem crs1,
                                        final CoordinateReferenceSystem crs2, final boolean debug)
    {
        return (crs1 == null) || (crs2 == null) || Utilities.deepEquals(crs1, crs2,
                debug ? ComparisonMode.DEBUG : ComparisonMode.IGNORE_METADATA);
    }

    /**
     * Returns the common CRS of specified points.
     *
     * @param  lowerCorner  the first position.
     * @param  upperCorner  the second position.
     * @return their common CRS, or {@code null} if none.
     * @throws MismatchedReferenceSystemException if the two positions don't use equal CRS.
     */
    static CoordinateReferenceSystem getCommonCRS(final DirectPosition lowerCorner,
                                                  final DirectPosition upperCorner)
            throws MismatchedReferenceSystemException
    {
        ensureNonNull("lowerCorner", lowerCorner);
        ensureNonNull("upperCorner", upperCorner);
        final CoordinateReferenceSystem crs1 = lowerCorner.getCoordinateReferenceSystem();
        final CoordinateReferenceSystem crs2 = upperCorner.getCoordinateReferenceSystem();
        if (crs1 == null) {
            return crs2;
        } else {
            if (crs2 != null && !crs1.equals(crs2)) {
                throw new MismatchedReferenceSystemException(Errors.format(Errors.Keys.MismatchedCRS));
            }
            return crs1;
        }
    }

    /**
     * Returns the axis of the given coordinate reference system for the given dimension,
     * or {@code null} if none.
     *
     * @param  crs        the envelope CRS, or {@code null}.
     * @param  dimension  the dimension for which to get the axis.
     * @return the axis at the given dimension, or {@code null}.
     */
    static CoordinateSystemAxis getAxis(final CoordinateReferenceSystem crs, final int dimension) {
        if (crs != null) {
            final CoordinateSystem cs = crs.getCoordinateSystem();
            if (cs != null) {                                       // Paranoiac check (should never be null).
                return cs.getAxis(dimension);
            }
        }
        return null;
    }

    /**
     * Returns {@code true} if the axis for the given dimension has the
     * {@link RangeMeaning#WRAPAROUND WRAPAROUND} range meaning.
     *
     * @param  crs        the envelope CRS, or {@code null}.
     * @param  dimension  the dimension for which to get the axis.
     * @return {@code true} if the range meaning is {@code WRAPAROUND}.
     */
    static boolean isWrapAround(final CoordinateReferenceSystem crs, final int dimension) {
        return isWrapAround(getAxis(crs, dimension));
    }

    /**
     * Returns {@code true} if the given axis is non-null and has the
     * {@link RangeMeaning#WRAPAROUND WRAPAROUND} range meaning.
     *
     * @param  axis  the axis to test, or {@code null}.
     * @return {@code true} if the range meaning is {@code WRAPAROUND}.
     */
    static boolean isWrapAround(final CoordinateSystemAxis axis) {
        return (axis != null) && RangeMeaning.WRAPAROUND.equals(axis.getRangeMeaning());
    }

    /**
     * If the range meaning of the given axis is "wraparound", returns the spanning of that axis.
     * Otherwise returns {@link Double#NaN}.
     *
     * @param  axis  the axis for which to get the spanning.
     * @return the spanning of the given axis.
     */
    static double getSpan(final CoordinateSystemAxis axis) {
        if (isWrapAround(axis)) {
            return axis.getMaximumValue() - axis.getMinimumValue();
        }
        return Double.NaN;
    }

    /**
     * Returns {@code true} if the given value is negative, without checks for {@code NaN}.
     * This method should be invoked only when the number is known to not be {@code NaN},
     * otherwise the safer {@link org.apache.sis.math.MathFunctions#isNegative(double)} method
     * shall be used instead. Note that the check for {@code NaN} doesn't need to be explicit.
     * For example in the following code, {@code NaN} values were implicitly checked by
     * the {@code (a < b)} comparison:
     *
     * {@preformat java
     *     if (a < b && isNegativeUnsafe(a)) {
     *         // ... do some stuff
     *     }
     * }
     */
    static boolean isNegativeUnsafe(final double value) {
        return (Double.doubleToRawLongBits(value) & SIGN_BIT_MASK) != 0;
    }

    /**
     * A coordinate position consisting of all the lower coordinate values.
     * The default implementation returns a view over the {@link #getLower(int)} method,
     * so changes in this envelope will be immediately reflected in the returned direct position.
     * If the particular case of the {@code GeneralEnvelope} subclass, the returned position
     * supports also {@linkplain DirectPosition#setOrdinate(int, double) write operations},
     * so changes in the position are reflected back in the envelope.
     *
     * <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 crossing 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 view over the lower corner, typically (but not necessarily) containing minimal coordinate values.
     */
    @Override
    public DirectPosition getLowerCorner() {
        // We do not cache the object because it is very cheap to create and we
        // do not want to increase the size of every AbstractEnvelope instances.
        return new LowerCorner();
    }

    /**
     * A coordinate position consisting of all the upper coordinate values.
     * The default implementation returns a view over the {@link #getUpper(int)} method,
     * so changes in this envelope will be immediately reflected in the returned direct position.
     * If the particular case of the {@code GeneralEnvelope} subclass, the returned position
     * supports also {@linkplain DirectPosition#setOrdinate(int, double) write operations},
     * so changes in the position are reflected back in the envelope.
     *
     * <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 crossing 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 view over the upper corner, typically (but not necessarily) containing maximal coordinate values.
     */
    @Override
    public DirectPosition getUpperCorner() {
        // We do not cache the object because it is very cheap to create and we
        // do not want to increase the size of every AbstractEnvelope instances.
        return new UpperCorner();
    }

    /**
     * A coordinate position consisting of all the median coordinate values.
     * The default implementation returns a view over the {@link #getMedian(int)} method,
     * so changes in this envelope will be immediately reflected in the returned direct position.
     *
     * @return the median coordinates.
     */
    public DirectPosition getMedian() {
        // We do not cache the object because it is very cheap to create and we
        // do not want to increase the size of every AbstractEnvelope instances.
        return new Median();
    }

    /**
     * Returns the limit in the direction of decreasing coordinate values in the specified dimension.
     * This is usually the algebraic {@linkplain #getMinimum(int) minimum}, except if this envelope
     * spans the anti-meridian.
     *
     * @param  dimension  the dimension for which to obtain the coordinate value.
     * @return the starting coordinate value at the given dimension.
     * @throws IndexOutOfBoundsException if the given index is negative or is equals or greater
     *         than the {@linkplain #getDimension() envelope dimension}.
     */
    public abstract double getLower(int dimension) throws IndexOutOfBoundsException;

    /**
     * Returns the limit in the direction of increasing coordinate values in the specified dimension.
     * This is usually the algebraic {@linkplain #getMaximum(int) maximum}, except if this envelope
     * spans the anti-meridian.
     *
     * @param  dimension  the dimension for which to obtain the coordinate value.
     * @return the starting coordinate value at the given dimension.
     * @throws IndexOutOfBoundsException if the given index is negative or is equals or greater
     *         than the {@linkplain #getDimension() envelope dimension}.
     */
    public abstract double getUpper(int dimension) throws IndexOutOfBoundsException;

    /**
     * Returns the minimal coordinate value for the specified dimension. In the typical case
     * of non-empty envelopes <em>not</em> spanning the anti-meridian, this method returns the
     * {@link #getLower(int)} value verbatim. In the case of envelope spanning the anti-meridian,
     * this method returns the {@linkplain CoordinateSystemAxis#getMinimumValue() axis minimum value}.
     * If the range in the given dimension is invalid, then this method returns {@code NaN}.
     *
     * @param  dimension  the dimension for which to obtain the coordinate value.
     * @return the minimal coordinate value at the given dimension.
     * @throws IndexOutOfBoundsException if the given index is negative or is equals or greater
     *         than the {@linkplain #getDimension() envelope dimension}.
     */
    @Override
    public double getMinimum(final int dimension) throws IndexOutOfBoundsException {
        double lower = getLower(dimension);
        if (isNegative(getUpper(dimension) - lower)) {              // Special handling for -0.0
            final CoordinateSystemAxis axis = getAxis(getCoordinateReferenceSystem(), dimension);
            lower = isWrapAround(axis) ? axis.getMinimumValue() : Double.NaN;
        }
        return lower;
    }

    /**
     * Returns the maximal coordinate value for the specified dimension. In the typical case
     * of non-empty envelopes <em>not</em> spanning the anti-meridian, this method returns the
     * {@link #getUpper(int)} value verbatim. In the case of envelope spanning the anti-meridian,
     * this method returns the {@linkplain CoordinateSystemAxis#getMaximumValue() axis maximum value}.
     * If the range in the given dimension is invalid, then this method returns {@code NaN}.
     *
     * @param  dimension  the dimension for which to obtain the coordinate value.
     * @return the maximal coordinate value at the given dimension.
     * @throws IndexOutOfBoundsException if the given index is negative or is equals or greater
     *         than the {@linkplain #getDimension() envelope dimension}.
     */
    @Override
    public double getMaximum(final int dimension) throws IndexOutOfBoundsException {
        double upper = getUpper(dimension);
        if (isNegative(upper - getLower(dimension))) {              // Special handling for -0.0
            final CoordinateSystemAxis axis = getAxis(getCoordinateReferenceSystem(), dimension);
            upper = isWrapAround(axis) ? axis.getMaximumValue() : Double.NaN;
        }
        return upper;
    }

    /**
     * Returns the median coordinate along the specified dimension.
     * In most cases, the result is equals (minus rounding error) to:
     *
     * {@preformat java
     *     median = (getUpper(dimension) + getLower(dimension)) / 2;
     * }
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * If <var>upper</var> &lt; <var>lower</var> and the
     * {@linkplain CoordinateSystemAxis#getRangeMeaning() range meaning} for the requested
     * dimension is {@linkplain RangeMeaning#WRAPAROUND wraparound}, then the median calculated
     * above is actually in the middle of the space <em>outside</em> the envelope. In such cases,
     * this method shifts the <var>median</var> value by half of the periodicity (180° in the
     * longitude case) in order to switch from <cite>outer</cite> space to <cite>inner</cite>
     * space. If the axis range meaning is not {@code WRAPAROUND}, then this method returns
     * {@link Double#NaN NaN}.
     *
     * @param  dimension  the dimension for which to obtain the coordinate value.
     * @return the median coordinate at the given dimension, or {@link Double#NaN}.
     * @throws IndexOutOfBoundsException if the given index is negative or is equals or greater
     *         than the {@linkplain #getDimension() envelope dimension}.
     */
    @Override
    public double getMedian(final int dimension) throws IndexOutOfBoundsException {
        final double lower = getLower(dimension);
        final double upper = getUpper(dimension);
        double median = 0.5 * (lower + upper);
        if (isNegative(upper - lower)) {                            // Special handling for -0.0
            median = fixMedian(getAxis(getCoordinateReferenceSystem(), dimension), median);
        }
        return median;
    }

    /**
     * Shifts the median value when the minimum is greater than the maximum.
     * If no shift can be applied, returns {@code NaN}.
     */
    static double fixMedian(final CoordinateSystemAxis axis, final double median) {
        if (isWrapAround(axis)) {
            final double minimum = axis.getMinimumValue();
            final double maximum = axis.getMaximumValue();
            final double cycle   = maximum - minimum;
            if (cycle > 0 && cycle != Double.POSITIVE_INFINITY) {
                // The copySign is for shifting in the direction of the valid range center.
                return median + 0.5 * Math.copySign(cycle, 0.5*(minimum + maximum) - median);
            }
        }
        return Double.NaN;
    }

    /**
     * Returns the envelope span (typically width or height) along the specified dimension.
     * In most cases, the result is equals (minus rounding error) to:
     *
     * {@preformat java
     *     span = getUpper(dimension) - getLower(dimension);
     * }
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * If <var>upper</var> &lt; <var>lower</var> and the
     * {@linkplain CoordinateSystemAxis#getRangeMeaning() range meaning} for the requested
     * dimension is {@linkplain RangeMeaning#WRAPAROUND wraparound}, then the span calculated
     * above is negative. In such cases, this method adds the periodicity (typically 360° of
     * longitude) to the span. If the result is a positive number, it is returned. Otherwise
     * this method returns {@link Double#NaN NaN}.
     *
     * @param  dimension  the dimension for which to obtain the span.
     * @return the span (typically width or height) at the given dimension, or {@link Double#NaN}.
     * @throws IndexOutOfBoundsException if the given index is negative or is equals or greater
     *         than the {@linkplain #getDimension() envelope dimension}.
     */
    @Override
    public double getSpan(final int dimension) {
        double span = getUpper(dimension) - getLower(dimension);
        if (isNegative(span)) {                                     // Special handling for -0.0
            span = fixSpan(getAxis(getCoordinateReferenceSystem(), dimension), span);
        }
        return span;
    }

    /**
     * Transforms a negative span into a valid value if the axis range meaning is "wraparound".
     * Returns {@code NaN} otherwise.
     *
     * @param  axis  the axis for the span dimension, or {@code null}.
     * @param  span  the negative span.
     * @return a positive span, or NaN if the span can not be fixed.
     */
    static double fixSpan(final CoordinateSystemAxis axis, double span) {
        if (isWrapAround(axis)) {
            final double cycle = axis.getMaximumValue() - axis.getMinimumValue();
            if (cycle > 0 && cycle != Double.POSITIVE_INFINITY) {
                span += cycle;
                if (span >= 0) {
                    return span;
                }
            }
        }
        return Double.NaN;
    }

    /**
     * Returns the envelope span along the specified dimension, in terms of the given units.
     * The default implementation invokes {@link #getSpan(int)} and converts the result.
     *
     * @param  dimension  the dimension to query.
     * @param  unit  the unit for the return value.
     * @return the span in terms of the given unit.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     * @throws IncommensurableException if the length can't be converted to the specified units.
     */
    public double getSpan(final int dimension, final Unit<?> unit)
            throws IndexOutOfBoundsException, IncommensurableException
    {
        double value = getSpan(dimension);
        final CoordinateSystemAxis axis = getAxis(getCoordinateReferenceSystem(), dimension);
        if (axis != null) {
            final Unit<?> source = axis.getUnit();
            if (source != null) {
                value = source.getConverterToAny(unit).convert(value);
            }
        }
        return value;
    }

    /**
     * Returns this envelope as an array of simple (without wraparound) envelopes.
     * The length of the returned array depends on the number of dimensions where a
     * {@linkplain org.opengis.referencing.cs.RangeMeaning#WRAPAROUND wraparound} range is found.
     * Typically, wraparound occurs only in the range of longitude values, when the range crosses
     * the anti-meridian (a.k.a. date line). However this implementation will take in account any
     * axis having wraparound {@linkplain CoordinateSystemAxis#getRangeMeaning() range meaning}.
     *
     * <p>Special cases:</p>
     *
     * <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 {@code this}
     *       in an array of length 1. This envelope is <strong>not</strong> cloned.</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 simple envelopes.
     *   <li>While uncommon, the envelope could theoretically crosses the limit of other axis having
     *       wraparound range meaning. If wraparound occur along <var>n</var> axes, then this method
     *       represents this envelope as 2ⁿ separated simple envelopes.
     * </ul>
     *
     * @return a representation of this envelope as an array of non-empty envelope.
     *
     * @see Envelope2D#toRectangles()
     * @see GeneralEnvelope#simplify()
     *
     * @since 0.4
     */
    @SuppressWarnings("ReturnOfCollectionOrArrayField")
    public Envelope[] toSimpleEnvelopes() {
        long isWrapAround = 0;                              // A bitmask of the dimensions having a "wrap around" behavior.
        CoordinateReferenceSystem crs = null;
        final int dimension = getDimension();
        for (int i=0; i!=dimension; i++) {
            final double span = getUpper(i) - getLower(i);  // Do not use getSpan(i).
            if (!(span > 0)) {                              // Use '!' for catching NaN.
                if (!isNegative(span)) {
                    return EMPTY;                           // Span is positive zero.
                }
                if (crs == null) {
                    crs = getCoordinateReferenceSystem();
                }
                if (!isWrapAround(crs, i)) {
                    return EMPTY;
                }
                if (i >= Long.SIZE) {
                    // Actually the limit in our current implementation is not the number of axes, but the index of
                    // axes where a wraparound has been found. However we consider that having more than 64 axes in
                    // a CRS is unusual enough for not being worth to make the distinction in the error message.
                    throw new IllegalStateException(Errors.format(Errors.Keys.ExcessiveListSize_2, "axis", dimension));
                }
                isWrapAround |= (1L << i);
            }
        }
        /*
         * The number of simple envelopes is 2ⁿ where n is the number of wraparound found. In most
         * cases, isWrapAround == 0 so we have an array of length 1 containing only this envelope.
         */
        final int bitCount = Long.bitCount(isWrapAround);
        if (bitCount >= Integer.SIZE - 1) {
            // Should be very unusual, but let be paranoiac.
            throw new IllegalStateException(Errors.format(Errors.Keys.ExcessiveListSize_2, "wraparound", bitCount));
        }
        final Envelope[] envelopes = new Envelope[1 << bitCount];
        if (envelopes.length == 1) {
            envelopes[0] = this;
        } else {
            /*
             * Need to create at least 2 envelopes. Instantiate now all envelopes with coordinate values
             * initialized to a copy of this envelope. We will write directly in their internal arrays later.
             */
            double[] c = new double[dimension * 2];
            for (int i=0; i<dimension; i++) {
                c[i            ] = getLower(i);
                c[i + dimension] = getUpper(i);
            }
            final double[][] coordinates = new double[envelopes.length][];
            for (int i=0; i<envelopes.length; i++) {
                final GeneralEnvelope envelope = new GeneralEnvelope(i == 0 ? c : c.clone());
                envelope.crs = crs;
                envelopes[i] = envelope;
                coordinates[i] = envelope.coordinates;
            }
            /*
             * Assign the minimum and maximum coordinate values in the dimension where a wraparound has been found.
             * The 'for' loop below iterates only over the 'i' values for which the 'isWrapAround' bit is set to 1.
             */
            int mask = 1;               // For identifying whether we need to set the lower or the upper coordinate.
            @SuppressWarnings("null")
            final CoordinateSystem cs = crs.getCoordinateSystem();            // Should not be null at this point.
            for (int i; (i = Long.numberOfTrailingZeros(isWrapAround)) != Long.SIZE; isWrapAround &= ~(1L << i)) {
                final CoordinateSystemAxis axis = cs.getAxis(i);
                final double min = axis.getMinimumValue();
                final double max = axis.getMaximumValue();
                for (int j=0; j<coordinates.length; j++) {
                    c = coordinates[j];
                    if ((j & mask) == 0) {
                        c[i + dimension] = max;
                    } else {
                        c[i] = min;
                    }
                }
                mask <<= 1;
            }
        }
        return envelopes;
    }

    /**
     * Determines whether or not this envelope is empty. An envelope is empty if it has zero
     * {@linkplain #getDimension() dimension}, or if the {@linkplain #getSpan(int) span} of
     * at least one axis is negative, 0 or {@link Double#NaN NaN}.
     *
     * <div class="note"><b>Note:</b>
     * Strictly speaking, there is an ambiguity if a span is {@code NaN} or if the envelope contains
     * both 0 and infinite spans (since 0⋅∞ = {@code NaN}). In such cases, this method arbitrarily
     * ignores the infinite values and returns {@code true}.</div>
     *
     * If {@code isEmpty()} returns {@code false}, then {@link #isAllNaN()} is guaranteed to
     * also return {@code false}. However the converse is not always true.
     *
     * @return {@code true} if this envelope is empty.
     *
     * @see org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#isEmpty()
     * @see java.awt.geom.Rectangle2D#isEmpty()
     */
    @Override
    public boolean isEmpty() {
        final int dimension = getDimension();
        if (dimension == 0) {
            return true;
        }
        for (int i=0; i<dimension; i++) {
            if (!(getSpan(i) > 0)) {                            // Use '!' in order to catch NaN
                return true;
            }
        }
        assert !isAllNaN() : this;
        return false;
    }

    /**
     * Returns {@code false} if at least one coordinate value is not {@linkplain Double#NaN NaN}.
     * This {@code isAllNaN()} check is different than the {@link #isEmpty()} check since it
     * returns {@code false} for a partially initialized envelope, while {@code isEmpty()}
     * returns {@code false} only after all dimensions have been initialized.
     * More specifically, the following rules apply:
     *
     * <ul>
     *   <li>If {@code isAllNaN() == true}, then {@code isEmpty() == true}</li>
     *   <li>If {@code isEmpty() == false}, then {@code isAllNaN() == false}</li>
     *   <li>The converse of the above-cited rules are not always true.</li>
     * </ul>
     *
     * Note that an all-NaN envelope can still have a non-null
     * {@linkplain #getCoordinateReferenceSystem() coordinate reference system}.
     *
     * @return {@code true} if this envelope has NaN values.
     *
     * @see GeneralEnvelope#setToNaN()
     * @see org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#isEmpty()
     */
    public boolean isAllNaN() {
        final int dimension = getDimension();
        for (int i=0; i<dimension; i++) {
            if (!Double.isNaN(getLower(i)) || !Double.isNaN(getUpper(i))) {
                return false;
            }
        }
        assert isEmpty() : this;
        return true;
    }

    /**
     * Tests if a specified coordinate is inside the boundary of this envelope.
     * Both lower and upper values of this envelope are considered inclusive.
     * If it least one coordinate value in the given point is {@link Double#NaN NaN},
     * then this method returns {@code false}.
     *
     * <h4>Pre-conditions</h4>
     * This method assumes that the specified point uses the same CRS than this envelope.
     * For performance reasons, it will no be verified unless Java assertions are enabled.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * For any dimension, if <var>upper</var> &lt; <var>lower</var> then this method uses an
     * algorithm which is the opposite of the usual one: rather than testing if the given point is
     * inside the envelope interior, this method tests if the given point is <em>outside</em> the
     * envelope <em>exterior</em>.
     *
     * @param  position  the point to text.
     * @return {@code true} if the specified coordinate is inside the boundary of this envelope; {@code false} otherwise.
     * @throws MismatchedDimensionException if the specified point does not have the expected number of dimensions.
     * @throws AssertionError if assertions are enabled and the envelopes have mismatched CRS.
     */
    public boolean contains(final DirectPosition position) throws MismatchedDimensionException {
        ensureNonNull("position", position);
        final int dimension = getDimension();
        ensureDimensionMatches("point", dimension, position);
        assert equalsIgnoreMetadata(getCoordinateReferenceSystem(),
                position.getCoordinateReferenceSystem(), true) : position;
        for (int i=0; i<dimension; i++) {
            final double value = position.getOrdinate(i);
            final double lower = getLower(i);
            final double upper = getUpper(i);
            final boolean c1   = (value >= lower);
            final boolean c2   = (value <= upper);
            if (c1 & c2) {
                continue;               // Point inside the range, check other dimensions.
            }
            if (c1 | c2) {
                if (isNegative(upper - lower)) {
                    /*
                     * "Spanning the anti-meridian" case: if we reach this point, then the
                     * [upper...lower] range  (note the 'lower' and 'upper' interchanging)
                     * is actually a space outside the envelope and we have checked that
                     * the coordinate value is outside that space.
                     */
                    continue;
                }
            }
            return false;
        }
        return true;
    }

    /**
     * Returns {@code true} if this envelope completely encloses the specified envelope.
     * The default implementation delegates to:
     *
     * <blockquote><pre>{@linkplain #contains(Envelope, boolean) contains}(envelope, <b>true</b>)</pre></blockquote>
     *
     * <h4>Pre-conditions</h4>
     * This method assumes that the specified envelope uses the same CRS than this envelope.
     * For performance reasons, it will no be verified unless Java assertions are enabled.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * For every cases illustrated below, the yellow box is considered completely enclosed
     * in the blue envelope:
     *
     * <p><img src="doc-files/Contains.png" alt="Examples of envelope inclusions"></p>
     *
     * @param  envelope  the envelope to test for inclusion.
     * @return {@code true} if this envelope completely encloses the specified one.
     * @throws MismatchedDimensionException if the specified envelope doesn't have the expected dimension.
     * @throws AssertionError if assertions are enabled and the envelopes have mismatched CRS.
     *
     * @see #intersects(Envelope)
     * @see #equals(Envelope, double, boolean)
     *
     * @since 0.4
     */
    public boolean contains(final Envelope envelope) throws MismatchedDimensionException {
        return contains(envelope, true);
    }

    /**
     * Returns {@code true} if this envelope completely encloses the specified envelope.
     * If one or more edges from the specified envelope coincide with an edge from this
     * envelope, then this method returns {@code true} only if {@code edgesInclusive}
     * is {@code true}.
     *
     * <p>This method is subject to the same pre-conditions than {@link #contains(Envelope)},
     * and handles envelopes spanning the anti-meridian in the same way.</p>
     *
     * @param  envelope        the envelope to test for inclusion.
     * @param  edgesInclusive  {@code true} if this envelope edges are inclusive.
     * @return {@code true} if this envelope completely encloses the specified one.
     * @throws MismatchedDimensionException if the specified envelope doesn't have the expected dimension.
     * @throws AssertionError if assertions are enabled and the envelopes have mismatched CRS.
     *
     * @see #intersects(Envelope, boolean)
     */
    public boolean contains(final Envelope envelope, final boolean edgesInclusive) throws MismatchedDimensionException {
        ensureNonNull("envelope", envelope);
        final int dimension = getDimension();
        ensureDimensionMatches("envelope", dimension, envelope);
        assert equalsIgnoreMetadata(getCoordinateReferenceSystem(),
                envelope.getCoordinateReferenceSystem(), true) : envelope;
        final DirectPosition lowerCorner = envelope.getLowerCorner();
        final DirectPosition upperCorner = envelope.getUpperCorner();
        for (int i=0; i<dimension; i++) {
            final double lower0 = getLower(i);
            final double upper0 = getUpper(i);
            final double lower1 = lowerCorner.getOrdinate(i);
            final double upper1 = upperCorner.getOrdinate(i);
            final boolean lowerCondition, upperCondition;
            if (edgesInclusive) {
                lowerCondition = (lower1 >= lower0);
                upperCondition = (upper1 <= upper0);
            } else {
                lowerCondition = (lower1 > lower0);
                upperCondition = (upper1 < upper0);
            }
            if (lowerCondition & upperCondition) {
                /*         upperCnd          upperCnd
                 *  ┌─────────────┐          ────┐  ┌────                      ┌─┐
                 *  │  ┌───────┐  │    or    ──┐ │  │ ┌──    excluding    ───┐ │ │ ┌───
                 *  │  └───────┘  │          ──┘ │  │ └──                 ───┘ │ │ └───
                 *  └─────────────┘          ────┘  └────                      └─┘
                 *  lowerCnd                        lowerCnd
                 */
                // (upper1-lower1) is negative if the small rectangle in above pictures spans the anti-meridian.
                if (!isNegativeUnsafe(upper1 - lower1) || isNegativeUnsafe(upper0 - lower0)) {
                    // Not the excluded case, go to next dimension.
                    continue;
                }
                /*
                 * If this envelope does not span the anti-meridian but the given envelope does,
                 * then this envelope does not contain the given envelope except in the special
                 * case where the envelope spanning is equals or greater than the axis spanning
                 * (including the case where this envelope expands to infinities).
                 */
                if ((lower0 == Double.NEGATIVE_INFINITY && upper0 == Double.POSITIVE_INFINITY) ||
                    (upper0 - lower0 >= getSpan(getAxis(getCoordinateReferenceSystem(), i))))
                {
                    continue;
                }
            } else if (lowerCondition != upperCondition) {
                /*     upperCnd                     !upperCnd
                 *  ──────────┐  ┌─────              ─────┐  ┌─────────
                 *    ┌────┐  │  │           or           │  │  ┌────┐
                 *    └────┘  │  │                        │  │  └────┘
                 *  ──────────┘  └─────              ─────┘  └─────────
                 *               !lowerCnd                   lowerCnd */
                if (isNegative(upper0 - lower0)) {
                    if (isPositive(upper1 - lower1)) {
                        continue;
                    }
                    // Special case for the [0…-0] range, if inclusive.
                    if (edgesInclusive && Double.doubleToRawLongBits(lower0) == 0L &&
                            Double.doubleToRawLongBits(upper0) == SIGN_BIT_MASK)
                    {
                        continue;
                    }
                }
            } else if (isNegativeZero(upper0 - lower0)) {
                /*      !upperCnd
                 *  ────────┬────────
                 *        ┌─┼────┐
                 *        └─┼────┘
                 *  ────────┴────────
                 *      !lowerCnd */
                continue;
            }
            return false;
        }
        // The check for ArrayEnvelope.class is for avoiding never-ending callbacks.
        assert envelope.getClass() == ArrayEnvelope.class ||
               intersects(new ArrayEnvelope(envelope), edgesInclusive) : envelope;
        return true;
    }

    /**
     * Returns {@code true} if this envelope intersects the specified envelope.
     * This method returns {@code true} if two envelope <em>interiors</em> have at least one point in common
     * (in other words, their intersection is non-{@linkplain #isEmpty() empty}).
     * The default implementation delegates to:
     *
     * <blockquote><pre>{@linkplain #intersects(Envelope, boolean) intersects}(envelope, <b>false</b>)</pre></blockquote>
     *
     * <h4>Pre-conditions</h4>
     * This method assumes that the specified envelope uses the same CRS than this envelope.
     * For performance reasons, it will no be verified unless Java assertions are enabled.
     *
     * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
     * This method can handle envelopes spanning the anti-meridian.
     *
     * @param  envelope  the envelope to test for intersection.
     * @return {@code true} if this envelope intersects the specified one.
     * @throws MismatchedDimensionException if the specified envelope doesn't have the expected dimension.
     * @throws AssertionError if assertions are enabled and the envelopes have mismatched CRS.
     *
     * @see #contains(Envelope, boolean)
     * @see #equals(Envelope, double, boolean)
     *
     * @since 0.4
     */
    public boolean intersects(final Envelope envelope) throws MismatchedDimensionException {
        return intersects(envelope, false);
    }

    /**
     * Returns {@code true} if this envelope intersects or (optionally) touches the specified envelope.
     * The {@code touch} argument controls the value to return if only the envelope boundaries
     * (not the interiors) have a point in common:
     *
     * <ul>
     *   <li>If {@code false}, this method returns {@code true} if the intersection between the two envelopes
     *       is non-{@linkplain #isEmpty() empty} (i.e. the envelope <em>interiors</em> have points in common).
     *       This is the usual definition of {@code intersects} operation.</li>
     *   <li>If {@code true}, this method returns {@code true} if the two envelopes intersect each other
     *       <em>or</em> touch each other.</li>
     * </ul>
     *
     * This method is subject to the same pre-conditions than {@link #intersects(Envelope)},
     * and handles envelopes spanning the anti-meridian in the same way.
     *
     * @param  envelope  the envelope to test for intersection.
     * @param  touch     the value to return if the two envelopes touch each other.
     * @return {@code true} if this envelope intersects the specified envelope, or
     *         {@code touch} if this envelope touches the specified envelope, or {@code false} otherwise.
     * @throws MismatchedDimensionException if the specified envelope does not have the expected dimension.
     * @throws AssertionError if assertions are enabled and the envelopes have mismatched CRS.
     *
     * @see #contains(Envelope, boolean)
     * @see #equals(Envelope, double, boolean)
     */
    public boolean intersects(final Envelope envelope, final boolean touch) throws MismatchedDimensionException {
        ensureNonNull("envelope", envelope);
        final int dimension = getDimension();
        ensureDimensionMatches("envelope", dimension, envelope);
        assert equalsIgnoreMetadata(getCoordinateReferenceSystem(),
                envelope.getCoordinateReferenceSystem(), true) : envelope;
        final DirectPosition lowerCorner = envelope.getLowerCorner();
        final DirectPosition upperCorner = envelope.getUpperCorner();
        for (int i=0; i<dimension; i++) {
            final double lower0 = getLower(i);
            final double upper0 = getUpper(i);
            final double lower1 = lowerCorner.getOrdinate(i);
            final double upper1 = upperCorner.getOrdinate(i);
            final boolean lowerCondition, upperCondition;
            if (touch) {
                lowerCondition = (lower1 <= upper0);
                upperCondition = (upper1 >= lower0);
            } else {
                lowerCondition = (lower1 < upper0);
                upperCondition = (upper1 > lower0);
            }
            if (upperCondition & lowerCondition) {
                /*     ┌──────────┐
                 *     │  ┌───────┼──┐
                 *     │  └───────┼──┘
                 *     └──────────┘ (this is the most standard case) */
                continue;
            }
            final boolean sp0 = isNegative(upper0 - lower0);
            final boolean sp1 = isNegative(upper1 - lower1);
            if (sp0 | sp1) {
                /*
                 * If both envelopes span the anti-meridian (sp0 & sp1), we have an unconditional
                 * intersection (since both envelopes extend to infinities). Otherwise we have one
                 * of the cases illustrated below. Note that the rectangle could also intersect on
                 * only once side.
                 *         ┌──────────┐                   ─────┐      ┌─────
                 *     ────┼───┐  ┌───┼────      or          ┌─┼──────┼─┐
                 *     ────┼───┘  └───┼────                  └─┼──────┼─┘
                 *         └──────────┘                   ─────┘      └───── */
                if ((sp0 & sp1) | (upperCondition | lowerCondition)) {
                    continue;
                }
            }
            // The check for ArrayEnvelope.class is for avoiding never-ending callbacks.
            assert envelope.getClass() == ArrayEnvelope.class || hasNaN(envelope) ||
                    !contains(new ArrayEnvelope(envelope), touch) : envelope;
            return false;
        }
        return true;
    }

    /**
     * Returns {@code true} if at least one coordinate in the given envelope
     * is {@link Double#NaN}. This is used for assertions only.
     */
    static boolean hasNaN(final Envelope envelope) {
        return hasNaN(envelope.getLowerCorner()) || hasNaN(envelope.getUpperCorner());
    }

    /**
     * Returns {@code true} if at least one coordinate in the given position
     * is {@link Double#NaN}. This is used for assertions only.
     */
    static boolean hasNaN(final DirectPosition position) {
        for (int i=position.getDimension(); --i>=0;) {
            if (Double.isNaN(position.getOrdinate(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * Compares to the specified envelope for equality up to the specified tolerance value.
     * The tolerance value {@code eps} can be either relative to the {@linkplain #getSpan(int)
     * envelope span} along each dimension or can be an absolute value (as for example some
     * ground resolution of a {@linkplain org.apache.sis.coverage.grid.GridCoverage grid coverage}).
     *
     * <ul>
     *   <li>If {@code epsIsRelative} is set to {@code true}, the actual tolerance value for a
     *       given dimension <var>i</var> is {@code eps} × {@code span} where {@code span}
     *       is the maximum of {@linkplain #getSpan(int) this envelope span} and the specified
     *       envelope span along dimension <var>i</var>.</li>
     *   <li>If {@code epsIsRelative} is set to {@code false}, the actual tolerance value for a
     *       given dimension <var>i</var> is {@code eps}.</li>
     * </ul>
     *
     * <div class="note"><b>Note:</b>
     * Relative tolerance values (as opposed to absolute tolerance values) help to workaround the
     * fact that tolerance value are CRS dependent. For example the tolerance value need to be
     * smaller for geographic CRS than for UTM projections, because the former typically has a
     * [-180…180]° range while the later can have a range of thousands of meters.</div>
     *
     * <h4>Coordinate Reference System</h4>
     * To be considered equal, the two envelopes must have the same {@linkplain #getDimension() dimension}
     * and their CRS must be {@linkplain org.apache.sis.util.Utilities#equalsIgnoreMetadata equals,
     * ignoring metadata}. If at least one envelope has a null CRS, then the CRS are ignored and the
     * coordinate values are compared as if the CRS were equal.
     *
     * @param  other          the envelope to compare with.
     * @param  eps            the tolerance value to use for numerical comparisons.
     * @param  epsIsRelative  {@code true} if the tolerance value should be relative to axis length,
     *                        or {@code false} if it is an absolute value.
     * @return {@code true} if the given object is equal to this envelope up to the given tolerance value.
     *
     * @see #contains(Envelope)
     * @see #intersects(Envelope)
     */
    public boolean equals(final Envelope other, final double eps, final boolean epsIsRelative) {
        ensureNonNull("other", other);
        final int dimension = getDimension();
        if (other.getDimension() != dimension || !equalsIgnoreMetadata(
                getCoordinateReferenceSystem(), other.getCoordinateReferenceSystem(), false))
        {
            return false;
        }
        final DirectPosition lowerCorner = other.getLowerCorner();
        final DirectPosition upperCorner = other.getUpperCorner();
        for (int i=0; i<dimension; i++) {
            double ε = eps;
            if (epsIsRelative) {
                final double span = Math.max(getSpan(i), other.getSpan(i));
                if (span > 0 && span < Double.POSITIVE_INFINITY) {
                    ε *= span;
                }
            }
            if (!epsilonEqual(getLower(i), lowerCorner.getOrdinate(i), ε) ||
                !epsilonEqual(getUpper(i), upperCorner.getOrdinate(i), ε))
            {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns {@code true} if the specified object is an envelope of the same class
     * with equals coordinates and {@linkplain #getCoordinateReferenceSystem() CRS}.
     *
     * <div class="note"><b>Implementation note:</b>
     * This implementation requires that the provided {@code object} argument is of the same class than this envelope.
     * We do not relax this rule since not every implementations in the SIS code base follow the same contract.</div>
     *
     * @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 == this) {
            return true;
        }
        if (object != null && object.getClass() == getClass()) {
            final AbstractEnvelope that = (AbstractEnvelope) object;
            final int dimension = getDimension();
            if (dimension == that.getDimension()) {
                for (int i=0; i<dimension; i++) {
                    if (doubleToLongBits(getLower(i)) != doubleToLongBits(that.getLower(i)) ||
                        doubleToLongBits(getUpper(i)) != doubleToLongBits(that.getUpper(i)))
                    {
                        assert !equals(that, 0.0, false) : this;
                        return false;
                    }
                }
                if (Objects.equals(this.getCoordinateReferenceSystem(),
                                   that.getCoordinateReferenceSystem()))
                {
                    assert hashCode() == that.hashCode() : this;
                    assert equals(that, 0.0, false) : this;
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Returns a hash value for this envelope.
     */
    @Override
    public int hashCode() {
        final int dimension = getDimension();
        int code = 1;
        boolean p = true;
        do {
            for (int i=0; i<dimension; i++) {
                code = code*31 + Double.hashCode(p ? getLower(i) : getUpper(i));
            }
        } while ((p = !p) == false);
        return code + Objects.hashCode(getCoordinateReferenceSystem());
    }

    /**
     * Formats this envelope as a "{@code BOX}" element.
     * The output is of the form "{@code BOX}<var>n</var>{@code D(}{@linkplain #getLowerCorner()
     * lower corner}{@code ,}{@linkplain #getUpperCorner() upper corner}{@code )}"
     * where <var>n</var> is the {@linkplain #getDimension() number of dimensions}.
     * The number of dimension is written only if different than 2.
     *
     * <div class="note"><b>Example:</b>
     *   <ul>
     *     <li>{@code BOX(-90 -180, 90 180)}</li>
     *     <li>{@code BOX3D(-90 -180 0, 90 180 1)}</li>
     *   </ul>
     * </div>
     *
     * <div class="note"><b>Note:</b>
     * The {@code BOX} element is not part of the standard <cite>Well Known Text</cite> (WKT) format.
     * However it is understood by many software libraries, for example GDAL and PostGIS.</div>
     *
     * This method formats the numbers as with {@link Double#toString(double)} (i.e. without fixed number of fraction digits).
     * The string returned by this method can be {@linkplain GeneralEnvelope#GeneralEnvelope(CharSequence) parsed}
     * by the {@code GeneralEnvelope} constructor.
     *
     * @return this envelope as a {@code BOX} or {@code BOX3D} (most typical dimensions) element.
     */
    @Override
    public String toString() {
        return toString(this, false);
    }

    /**
     * Implementation of the public {@link #toString()} and {@link Envelopes#toString(Envelope)}
     * methods for formatting a {@code BOX} element from an envelope.
     *
     * @param  envelope           the envelope to format.
     * @param  isSinglePrecision  {@code true} if every lower and upper corner values can be casted to {@code float}.
     * @return this envelope as a {@code BOX} or {@code BOX3D} (most typical dimensions) element.
     *
     * @see GeneralEnvelope#GeneralEnvelope(CharSequence)
     * @see CoordinateFormat
     * @see org.apache.sis.io.wkt
     */
    static String toString(final Envelope envelope, final boolean isSinglePrecision) {
        final int dimension = envelope.getDimension();
        final StringBuilder buffer = new StringBuilder(64).append("BOX");
        if (dimension != 2) {
            buffer.append(dimension).append('D');
        }
        if (dimension == 0) {
            buffer.append("()");
        } else {
            final DirectPosition lowerCorner = envelope.getLowerCorner();
            final DirectPosition upperCorner = envelope.getUpperCorner();
            boolean isUpper = false;
            do {                                                        // Executed exactly twice.
                for (int i=0; i<dimension; i++) {
                    buffer.append(i == 0 && !isUpper ? '(' : ' ');
                    final double coordinate = (isUpper ? upperCorner : lowerCorner).getOrdinate(i);
                    if (isSinglePrecision) {
                        buffer.append((float) coordinate);
                    } else {
                        buffer.append(coordinate);
                    }
                    trimFractionalPart(buffer);
                }
                buffer.append(isUpper ? ')' : ',');
            } while ((isUpper = !isUpper) == true);
        }
        return buffer.toString();
    }

    /**
     * Formats this envelope as a "{@code BOX}" element.
     * The output is of the form "{@code BOX}<var>n</var>{@code D[}{@linkplain #getLowerCorner()
     * lower corner}{@code ,}{@linkplain #getUpperCorner() upper corner}{@code ]}"
     * where <var>n</var> is the {@linkplain #getDimension() number of dimensions}.
     * The number of dimension is written only if different than 2.
     *
     * <div class="note"><b>Note:</b>
     * The {@code BOX} element is not part of the standard <cite>Well Known Text</cite> (WKT) format.
     * However it is understood by many software libraries, for example GDAL and PostGIS.</div>
     *
     * If the coordinate reference system is geodetic or projected, then coordinate values are formatted
     * with a precision equivalent to one centimetre on Earth (the actual number of fraction digits is
     * adjusted for the axis unit of measurement and the planet size if different than Earth).
     *
     * @param  formatter  the formatter where to format the inner content of this envelope.
     * @return the pseudo-WKT keyword, which is {@code "Box"} for this element.
     *
     * @since 1.0
     */
    @Override
    protected String formatTo(final Formatter formatter) {
        final Vector[] points = {
            Vector.create(getLowerCorner().getCoordinate()),
            Vector.create(getUpperCorner().getCoordinate())
        };
        formatter.append(points, WKTUtilities.suggestFractionDigits(getCoordinateReferenceSystem(), points));
        final int dimension = getDimension();
        String keyword = "Box";
        if (dimension != 2) {
            keyword = new StringBuilder(keyword).append(dimension).append('D').toString();
        }
        formatter.setInvalidWKT(Envelope.class, null);
        return keyword;
    }

    /**
     * Base class for unmodifiable direct positions backed by the enclosing envelope.
     * Subclasses must override the {@link #getOrdinate(int)} method in order to delegate
     * the work to the appropriate {@link AbstractEnvelope} method.
     *
     * <p>Instance of this class are serializable if the enclosing envelope is serializable.</p>
     *
     * @author  Martin Desruisseaux (IRD, Geomatys)
     * @version 0.3
     * @since   0.3
     * @module
     */
    private abstract class Point extends AbstractDirectPosition implements Serializable {
        private static final long serialVersionUID = -4868610696294317932L;

        /** The coordinate reference system in which the coordinate is given. */
        @Override public final CoordinateReferenceSystem getCoordinateReferenceSystem() {
            return AbstractEnvelope.this.getCoordinateReferenceSystem();
        }

        /** The length of coordinate sequence (the number of entries). */
        @Override public final int getDimension() {
            return AbstractEnvelope.this.getDimension();
        }
    }

    /**
     * The corner returned by {@link AbstractEnvelope#getLowerCorner()}.
     */
    private final class LowerCorner extends Point {
        private static final long serialVersionUID = 1310741484466506178L;

        @Override public double getOrdinate(final int dimension) throws IndexOutOfBoundsException {
            return getLower(dimension);
        }

        /** Sets the coordinate value along the specified dimension. */
        @Override public void setOrdinate(final int dimension, final double value) {
            setRange(dimension, value, getUpper(dimension));
        }
    }

    /**
     * The corner returned by {@link AbstractEnvelope#getUpperCorner()}.
     */
    private final class UpperCorner extends Point {
        private static final long serialVersionUID = -6458663549974061472L;

        @Override public double getOrdinate(final int dimension) throws IndexOutOfBoundsException {
            return getUpper(dimension);
        }

        /** Sets the coordinate value along the specified dimension. */
        @Override public void setOrdinate(final int dimension, final double value) {
            setRange(dimension, getLower(dimension), value);
        }
    }

    /**
     * The point returned by {@link AbstractEnvelope#getMedian()}.
     */
    private final class Median extends Point {
        private static final long serialVersionUID = -5826011018957321729L;

        @Override public double getOrdinate(final int dimension) throws IndexOutOfBoundsException {
            return getMedian(dimension);
        }

        /** Unsupported operation. */
        @Override public void setOrdinate(int dimension, double value) {
            throw new UnmodifiableGeometryException(Errors.format(Errors.Keys.UnmodifiableObject_1, getClass()));
        }
    }

    /**
     * Invoked by {@link LowerCorner} and {@link UpperCorner} when a coordinate is modified.
     * The default implementation throws an {@link UnmodifiableGeometryException} in every cases.
     * This method is overridden and made public by {@link GeneralEnvelope}.
     *
     * <p>The declaration in this {@code AbstractEnvelope} class is not public on purpose,
     * since this class intentionally have no public setter methods. This is necessary for
     * preserving the immutable aspect of {@link ImmutableEnvelope} subclass among others.</p>
     *
     * @param  dimension  the dimension to set.
     * @param  lower      the limit in the direction of decreasing coordinate values.
     * @param  upper      the limit in the direction of increasing coordinate values.
     * @throws UnmodifiableGeometryException if this envelope is not modifiable.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     * @throws IllegalArgumentException if {@code lower > upper}, this envelope has a CRS
     *         and the axis range meaning at the given dimension is not "wraparound".
     */
    void setRange(final int dimension, final double lower, final double upper)
            throws IndexOutOfBoundsException
    {
        throw new UnmodifiableGeometryException(Errors.format(Errors.Keys.UnmodifiableObject_1, getClass()));
    }
}
