/*
 * 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.Set;
import java.util.ConcurrentModificationException;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.opengis.referencing.operation.OperationNotFoundException;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.util.FactoryException;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
import org.apache.sis.referencing.operation.transform.AbstractMathTransform;
import org.apache.sis.internal.metadata.ReferencingServices;
import org.apache.sis.internal.referencing.CoordinateOperations;
import org.apache.sis.internal.referencing.DirectPositionView;
import org.apache.sis.internal.system.Loggers;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.Static;
import org.apache.sis.math.MathFunctions;

import static org.apache.sis.util.StringBuilders.trimFractionalPart;


/**
 * Transforms envelopes to new Coordinate Reference Systems, and miscellaneous utilities.
 *
 * <div class="section">Envelope transformations</div>
 * All {@code transform(…)} methods in this class take in account the curvature of the transformed shape.
 * For example the shape of a geographic envelope (figure below on the left side) is not rectangular in a
 * conic projection (figure below on the right side). In order to get the envelope represented by the red
 * rectangle, projecting the four corners of the geographic envelope is not sufficient since we would miss
 * the southerner part.
 *
 * <table class="sis">
 *   <caption>Example of curvature induced by a map projection</caption>
 *   <tr>
 *     <th>Envelope before map projection</th>
 *     <th>Shape of the projected envelope</th>
 *   </tr><tr>
 *     <td><img src="doc-files/GeographicArea.png" alt="Envelope in a geographic CRS"></td>
 *     <td><img src="doc-files/ConicArea.png" alt="Shape of the envelope transformed in a conic projection"></td>
 *   </tr>
 * </table>
 *
 * Apache SIS tries to detect the curvature by transforming intermediate points in addition to the corners.
 * While optional, it is strongly recommended that all {@code MathTransform} implementations involved in the
 * operation (directly or indirectly) support {@linkplain MathTransform#derivative(DirectPosition) derivative},
 * for more accurate calculation of curve extremum. This is the case of most Apache SIS implementations.
 *
 * <p>The {@code transform(…)} methods in this class expect an arbitrary {@link Envelope} with <strong>one</strong>
 * of the following arguments: {@link MathTransform}, {@link CoordinateOperation} or {@link CoordinateReferenceSystem}.
 * The recommended method is the one expecting a {@code CoordinateOperation} object,
 * since it contains sufficient information for handling the cases of envelopes that encompass a pole.
 * The method expecting a {@code CoordinateReferenceSystem} object is merely a convenience method that
 * infers the coordinate operation itself, but at the cost of performance if the same operation needs
 * to be applied on many envelopes.</p>
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @author  Johann Sorel (Geomatys)
 * @version 1.0
 *
 * @see org.apache.sis.metadata.iso.extent.Extents
 * @see CRS
 *
 * @since 0.3
 * @module
 */
public final class Envelopes extends Static {
    /**
     * Do not allow instantiation of this class.
     */
    private Envelopes() {
    }

    /**
     * Puts together a list of envelopes, each of them using an independent coordinate reference system.
     * The dimension of the returned envelope is the sum of the dimension of all components.
     * If all components have a coordinate reference system, then the returned envelope will
     * have a compound coordinate reference system.
     *
     * @param  components  the envelopes to aggregate in a single envelope, in the given order.
     * @return the aggregation of all given envelopes.
     * @throws FactoryException if the geodetic factory failed to create the compound CRS.
     *
     * @see org.apache.sis.referencing.CRS#compound(CoordinateReferenceSystem...)
     * @see org.apache.sis.referencing.operation.transform.MathTransforms#compound(MathTransform...)
     *
     * @since 1.0
     */
    public static Envelope compound(final Envelope... components) throws FactoryException {
        ArgumentChecks.ensureNonNull("components", components);
        int sum = 0;
        for (int i=0; i<components.length; i++) {
            final Envelope env = components[i];
            ArgumentChecks.ensureNonNullElement("components", i, env);
            sum += env.getDimension();
        }
        final GeneralEnvelope compound = new GeneralEnvelope(sum);
        CoordinateReferenceSystem[] crsComponents = null;
        int firstAffectedCoordinate = 0;
        for (int i=0; i<components.length; i++) {
            final Envelope env = components[i];
            final int dim = env.getDimension();
            compound.subEnvelope(firstAffectedCoordinate, firstAffectedCoordinate += dim).setEnvelope(env);
            if (i == 0) {
                final CoordinateReferenceSystem crs = env.getCoordinateReferenceSystem();
                if (crs != null) {
                    crsComponents = new CoordinateReferenceSystem[components.length];
                    crsComponents[0] = crs;
                }
            } else if (crsComponents != null) {
                if ((crsComponents[i] = env.getCoordinateReferenceSystem()) == null) {
                    crsComponents = null;               // Not all CRS are non-null.
                }
            }
        }
        if (firstAffectedCoordinate != sum) {
            // Should never happen unless the number of dimensions of an envelope changed during iteration.
            throw new ConcurrentModificationException();
        }
        if (crsComponents != null) {
            compound.setCoordinateReferenceSystem(CRS.compound(crsComponents));
        }
        return compound;
    }

    /**
     * Computes the union of all given envelopes, transforming them to a common CRS if necessary.
     * If all envelopes use the same CRS ({@link ComparisonMode#IGNORE_METADATA ignoring metadata})
     * or if the CRS of all envelopes is {@code null}, then the {@linkplain GeneralEnvelope#add(Envelope)
     * union is computed} without transforming any envelope. Otherwise all envelopes are transformed to a
     * {@linkplain CRS#suggestCommonTarget common CRS} before union is computed.
     * The CRS of the returned envelope may different than the CRS of all given envelopes.
     *
     * @param  envelopes  the envelopes for which to compute union. Null elements are ignored.
     * @return union of given envelopes, or {@code null} if the given array does not contain non-null elements.
     * @throws TransformException if this method can not determine a common CRS, or if a transformation failed.
     *
     * @see GeneralEnvelope#add(Envelope)
     *
     * @since 1.0
     */
    public static GeneralEnvelope union(final Envelope... envelopes) throws TransformException {
        return EnvelopeReducer.UNION.reduce(envelopes);
    }

    /**
     * Finds a mathematical operation from the CRS of the given source envelope to the CRS of the given target envelope.
     * For non-null georeferenced envelopes, this method is equivalent to the following code with {@code areaOfInterest}
     * computed as the union of the two envelopes:
     *
     * <blockquote><code>return {@linkplain CRS#findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem,
     * GeographicBoundingBox)} CRS.findOperation(source.getCoordinateReferenceSystem(), target.getCoordinateReferenceSystem(),
     * <var>areaOfInterest</var>)</code></blockquote>
     *
     * If at least one envelope is null or has no CRS, then this method returns {@code null}.
     *
     * @param  source  the source envelope, or {@code null}.
     * @param  target  the target envelope, or {@code null}.
     * @return the mathematical operation from {@code source} CRS to {@code target} CRS,
     *         or {@code null} if at least one argument is null or has no CRS.
     * @throws OperationNotFoundException if no operation was found between the given pair of CRS.
     * @throws FactoryException if the operation can not be created for another reason.
     *
     * @see CRS#findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox)
     *
     * @since 1.0
     */
    public static CoordinateOperation findOperation(final Envelope source, final Envelope target) throws FactoryException {
        if (source != null && target != null) {
            final CoordinateReferenceSystem sourceCRS, targetCRS;
            if ((sourceCRS = source.getCoordinateReferenceSystem()) != null &&
                (targetCRS = target.getCoordinateReferenceSystem()) != null)
            {
                /*
                 * Computing the area of interest (AOI) unconditionally would be harmless, but it is useless if the CRS
                 * are the same since the result will be identity anyway. Conversely we could skip AOI computation more
                 * often for example with the following condition instead of !=:
                 *
                 *     !Utilities.deepEquals(sourceCRS, targetCRS, ComparisonMode.ALLOW_VARIANT)
                 *
                 * but it would not be very advantageous if testing the condition is almost as long as computing the AOI.
                 * For now we keep != as a very cheap test which will work quite often.
                 */
                DefaultGeographicBoundingBox areaOfInterest = null;
                if (sourceCRS != targetCRS) try {
                    final DefaultGeographicBoundingBox targetAOI;
                    final ReferencingServices converter = ReferencingServices.getInstance();
                    areaOfInterest = converter.setBounds(source, null, "findOperation");                // Should be first.
                    targetAOI      = converter.setBounds(target, null, "findOperation");
                    if (areaOfInterest == null) {
                        areaOfInterest = targetAOI;
                    } else if (targetAOI != null) {
                        areaOfInterest.add(targetAOI);
                    }
                } catch (TransformException e) {
                    /*
                     * Note: we may succeed to transform 'source' and fail to transform 'target' to geographic bounding box,
                     * but the opposite is unlikely because 'source' should not have less dimensions than 'target'.
                     */
                    Logging.recoverableException(Logging.getLogger(Loggers.GEOMETRY), Envelopes.class, "findOperation", e);
                }
                return CRS.findOperation(sourceCRS, targetCRS, areaOfInterest);
            }
        }
        return null;
    }

    /**
     * Computes the intersection of all given envelopes, transforming them to a common CRS if necessary.
     * If all envelopes use the same CRS ({@link ComparisonMode#IGNORE_METADATA ignoring metadata})
     * or if the CRS of all envelopes is {@code null}, then the {@linkplain GeneralEnvelope#intersect(Envelope)
     * intersection is computed} without transforming any envelope. Otherwise all envelopes are transformed to a
     * {@linkplain CRS#suggestCommonTarget common CRS} before intersection is computed.
     * The CRS of the returned envelope may different than the CRS of all given envelopes.
     *
     * @param  envelopes  the envelopes for which to compute intersection. Null elements are ignored.
     * @return intersection of given envelopes, or {@code null} if the given array does not contain non-null elements.
     * @throws TransformException if this method can not determine a common CRS, or if a transformation failed.
     *
     * @see GeneralEnvelope#intersect(Envelope)
     *
     * @since 1.0
     */
    public static GeneralEnvelope intersect(final Envelope... envelopes) throws TransformException {
        return EnvelopeReducer.INTERSECT.reduce(envelopes);
    }

    /**
     * Invoked when a recoverable exception occurred. Those exceptions must be minor enough
     * that they can be silently ignored in most cases.
     */
    static void recoverableException(final Class<? extends Static> caller, final TransformException exception) {
        Logging.recoverableException(Logging.getLogger(Loggers.GEOMETRY), caller, "transform", exception);
    }

    /**
     * A buckle method for calculating derivative and coordinate transformation in a single step,
     * if the given {@code derivative} argument is {@code true}.
     *
     * @param  transform  the transform to use.
     * @param  srcPts     the array containing the source coordinate at offset 0.
     * @param  dstPts     the array into which the transformed coordinate is returned.
     * @param  dstOff     the offset to the location of the transformed point that is stored in the destination array.
     * @param  derivate   {@code true} for computing the derivative, or {@code false} if not needed.
     * @return the matrix of the transform derivative at the given source position,
     *         or {@code null} if the {@code derivate} argument is {@code false}.
     * @throws TransformException if the point can not be transformed
     *         or if a problem occurred while calculating the derivative.
     */
    @SuppressWarnings("null")
    static Matrix derivativeAndTransform(final MathTransform transform, final double[] srcPts,
            final double[] dstPts, final int dstOff, final boolean derivate) throws TransformException
    {
        if (transform instanceof AbstractMathTransform) {
            return ((AbstractMathTransform) transform).transform(srcPts, 0, dstPts, dstOff, derivate);
        }
        // Derivative must be calculated before to transform the coordinate.
        final Matrix derivative = derivate ? transform.derivative(
                new DirectPositionView.Double(srcPts, 0, transform.getSourceDimensions())) : null;
        transform.transform(srcPts, 0, dstPts, dstOff, 1);
        return derivative;
    }

    /**
     * Transforms the given envelope to the specified CRS. If any argument is null, or if the
     * {@linkplain GeneralEnvelope#getCoordinateReferenceSystem() envelope CRS} is null or the
     * same instance than the given target CRS, then the given envelope is returned unchanged.
     * Otherwise a new transformed envelope is returned.
     *
     * <div class="section">Performance tip</div>
     * If there is many envelopes to transform with the same source and target CRS, then it is more efficient
     * to get the {@link CoordinateOperation} or {@link MathTransform} instance once and invoke one of the
     * others {@code transform(…)} methods.
     *
     * @param  envelope   the envelope to transform (may be {@code null}).
     * @param  targetCRS  the target CRS (may be {@code null}).
     * @return a new transformed envelope, or directly {@code envelope} if no change was required.
     * @throws TransformException if a transformation was required and failed.
     *
     * @since 0.5
     */
    public static Envelope transform(Envelope envelope, final CoordinateReferenceSystem targetCRS)
            throws TransformException
    {
        if (envelope != null && targetCRS != null) {
            final CoordinateReferenceSystem sourceCRS = envelope.getCoordinateReferenceSystem();
            if (sourceCRS != targetCRS) {
                if (sourceCRS == null) {
                    // Slight optimization: just copy the given Envelope.
                    envelope = new GeneralEnvelope(envelope);
                    ((GeneralEnvelope) envelope).setCoordinateReferenceSystem(targetCRS);
                } else {
                    // TODO: create an CoordinateOperationContext with the envelope as geographic area.
                    //       May require that we optimize the search for CoordinateOperation with non-null context first.
                    //       See https://issues.apache.org/jira/browse/SIS-442
                    final CoordinateOperation operation;
                    try {
                        operation = CoordinateOperations.factory().createOperation(sourceCRS, targetCRS);
                    } catch (FactoryException exception) {
                        throw new TransformException(Errors.format(Errors.Keys.CanNotTransformEnvelope), exception);
                    }
                    envelope = transform(operation, envelope);
                }
                assert Utilities.deepEquals(targetCRS, envelope.getCoordinateReferenceSystem(), ComparisonMode.DEBUG);
            }
        }
        return envelope;
    }

    /**
     * Transforms an envelope using the given math transform.
     * The transformation is only approximated: the returned envelope may be bigger than necessary,
     * or smaller than required if the bounding box contains a pole.
     * The coordinate reference system of the returned envelope will be null.
     *
     * <div class="section">Limitation</div>
     * This method can not handle the case where the envelope contains the North or South pole,
     * or when it crosses the ±180° longitude, because {@link MathTransform} does not carry sufficient information.
     * For a more robust envelope transformation, use {@link #transform(CoordinateOperation, Envelope)} instead.
     *
     * @param  transform  the transform to use.
     * @param  envelope   envelope to transform, or {@code null}. This envelope will not be modified.
     * @return the transformed envelope, or {@code null} if {@code envelope} was null.
     * @throws TransformException if a transform failed.
     *
     * @see #transform(CoordinateOperation, Envelope)
     *
     * @since 0.5
     */
    public static GeneralEnvelope transform(final MathTransform transform, final Envelope envelope)
            throws TransformException
    {
        ArgumentChecks.ensureNonNull("transform", transform);
        return (envelope != null) ? transform(transform, envelope, null) : null;
    }

    /**
     * Implementation of {@link #transform(MathTransform, Envelope)} with the opportunity to
     * save the projected center coordinate.
     *
     * @param  targetPt  after this method call, the center of the source envelope projected to the target CRS.
     *                   The length of this array must be the number of target dimensions.
     *                   May be {@code null} if this information is not needed.
     */
    @SuppressWarnings("null")
    private static GeneralEnvelope transform(final MathTransform transform,
                                             final Envelope      envelope,
                                             final double[]      targetPt)
            throws TransformException
    {
        if (transform.isIdentity()) {
            /*
             * Slight optimization: Just copy the envelope. Note that we need to set the CRS
             * to null because we don't know what the target CRS was supposed to be. Even if
             * an identity transform often imply that the target CRS is the same one than the
             * source CRS, it is not always the case. The metadata may be differents, or the
             * transform may be a datum shift without Bursa-Wolf parameters, etc.
             */
            final GeneralEnvelope transformed = new GeneralEnvelope(envelope);
            transformed.setCoordinateReferenceSystem(null);
            if (targetPt != null) {
                for (int i=envelope.getDimension(); --i>=0;) {
                    targetPt[i] = transformed.getMedian(i);
                }
            }
            return transformed;
        }
        /*
         * Checks argument validity: envelope and math transform dimensions must be consistent.
         */
        final int sourceDim = transform.getSourceDimensions();
        final int targetDim = transform.getTargetDimensions();
        if (envelope.getDimension() != sourceDim) {
            throw new MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimension_2,
                      sourceDim, envelope.getDimension()));
        }
        /*
         * Allocates all needed objects. The power of 3 below is because the following `while` loop
         * uses a `pointIndex` to be interpreted as a number in base 3 (see the comment inside the loop).
         * The coordinate tuple to transform must be initialized to the minimal coordinate values.
         * This coordinate will be updated in the `switch` statement inside the `while` loop.
         */
        if (sourceDim >= 20) {          // Maximal value supported by Formulas.pow3(int) is 19.
            throw new IllegalArgumentException(Errors.format(Errors.Keys.ExcessiveNumberOfDimensions_1));
        }
        int             pointIndex            = 0;
        boolean         isDerivativeSupported = true;
        GeneralEnvelope transformed           = null;
        final Matrix[]  derivatives           = new Matrix[Math.toIntExact(MathFunctions.pow(3, sourceDim))];
        final double[]  coordinates           = new double[derivatives.length * targetDim];
        final double[]  sourcePt              = new double[sourceDim];
        for (int i=sourceDim; --i>=0;) {
            sourcePt[i] = envelope.getMinimum(i);
        }
        // A window over a single coordinate in the `coordinates` array.
        final DirectPositionView ordinatesView = new DirectPositionView.Double(coordinates, 0, targetDim);
        /*
         * Iterates over every minimal, maximal and median coordinate values (3 points) along each
         * dimension. The total number of iterations is 3 ^ (number of source dimensions).
         */
        transformPoint: while (true) {
            /*
             * Compute the derivative (optional operation). If this operation fails, we will
             * set a flag to 'false' so we don't try again for all remaining points. We try
             * to compute the derivative and the transformed point in a single operation if
             * we can. If we can not, we will compute those two information separately.
             *
             * Note that the very last point to be projected must be the envelope center.
             * There is usually no need to calculate the derivative for that last point,
             * but we let it does anyway for safety.
             */
            final int offset = pointIndex * targetDim;
            try {
                derivatives[pointIndex] = derivativeAndTransform(transform,
                        sourcePt, coordinates, offset, isDerivativeSupported);
            } catch (TransformException e) {
                if (!isDerivativeSupported) {
                    throw e;                    // Derivative were already disabled, so something went wrong.
                }
                isDerivativeSupported = false;
                transform.transform(sourcePt, 0, coordinates, offset, 1);
                recoverableException(Envelopes.class, e);       // Log only if the above call was successful.
            }
            /*
             * The transformed point has been saved for future reuse after the enclosing
             * 'while' loop. Now add the transformed point to the destination envelope.
             */
            if (transformed == null) {
                transformed = new GeneralEnvelope(targetDim);
                for (int i=0; i<targetDim; i++) {
                    final double value = coordinates[offset + i];
                    transformed.setRange(i, value, value);
                }
            } else {
                ordinatesView.offset = offset;
                transformed.add(ordinatesView);
            }
            /*
             * Get the next point coordinate. The 'coordinateIndex' variable is an index in base 3
             * having a number of digits equals to the number of source dimensions.  For example a
             * 4-D space have indexes ranging from "0000" to "2222" (numbers in base 3). The digits
             * are then mapped to minimal (0), maximal (1) or central (2) coordinates. The outer loop
             * stops when the counter roll back to "0000". Note that 'targetPt' must keep the value
             * of the last projected point, which must be the envelope center identified by "2222"
             * in the 4-D case.
             */
            int indexBase3 = ++pointIndex;
            for (int dim=sourceDim; --dim>=0; indexBase3 /= 3) {
                switch (indexBase3 % 3) {
                    case 0:  sourcePt[dim] = envelope.getMinimum(dim); break;   // Continue the loop.
                    case 1:  sourcePt[dim] = envelope.getMaximum(dim); continue transformPoint;
                    case 2:  sourcePt[dim] = envelope.getMedian (dim); continue transformPoint;
                    default: throw new AssertionError(indexBase3);     // Should never happen
                }
            }
            break;
        }
        assert pointIndex == derivatives.length : pointIndex;
        /*
         * At this point we finished to build an envelope from all sampled positions. Now iterate
         * over all points. For each point, iterate over all line segments from that point to a
         * neighbor median point.  Use the derivate information for approximating the transform
         * behavior in that area by a cubic curve. We can then find analytically the curve extremum.
         *
         * The same technic is applied in transform(MathTransform, Rectangle2D), except that in
         * the Rectangle2D case the calculation was bundled right inside the main loop in order
         * to avoid the need for storage.
         */
        DirectPosition temporary = null;
        final DirectPositionView sourceView = new DirectPositionView.Double(sourcePt, 0, sourceDim);
        final CurveExtremum extremum = new CurveExtremum();
        for (pointIndex=0; pointIndex < derivatives.length; pointIndex++) {
            final Matrix D1 = derivatives[pointIndex];
            if (D1 != null) {
                int indexBase3 = pointIndex, power3 = 1;
                for (int i=sourceDim; --i>=0; indexBase3 /= 3, power3 *= 3) {
                    final int digitBase3 = indexBase3 % 3;
                    if (digitBase3 != 2) { // Process only if we are not already located on the median along the dimension i.
                        final int medianIndex = pointIndex + power3 * (2 - digitBase3);
                        final Matrix D2 = derivatives[medianIndex];
                        if (D2 != null) {
                            final double xmin = envelope.getMinimum(i);
                            final double xmax = envelope.getMaximum(i);
                            final double x2   = envelope.getMedian (i);
                            final double x1   = (digitBase3 == 0) ? xmin : xmax;
                            final int offset1 = targetDim * pointIndex;
                            final int offset2 = targetDim * medianIndex;
                            for (int j=0; j<targetDim; j++) {
                                extremum.resolve(x1, coordinates[offset1 + j], D1.getElement(j,i),
                                                 x2, coordinates[offset2 + j], D2.getElement(j,i));
                                boolean isP2 = false;
                                do { // Executed exactly twice, one for each extremum point.
                                    final double x = isP2 ? extremum.ex2 : extremum.ex1;
                                    if (x > xmin && x < xmax) {
                                        final double y = isP2 ? extremum.ey2 : extremum.ey1;
                                        if (y < transformed.getMinimum(j) ||
                                            y > transformed.getMaximum(j))
                                        {
                                            /*
                                             * At this point, we have determined that adding the extremum point
                                             * would expand the envelope. However we will not add that point
                                             * directly because its position may not be quite right (since we
                                             * used a cubic curve approximation). Instead, we project the point
                                             * on the envelope border which is located vis-à-vis the extremum.
                                             */
                                            for (int ib3 = pointIndex, dim = sourceDim; --dim >= 0; ib3 /= 3) {
                                                final double coordinate;
                                                if (dim == i) {
                                                    coordinate = x;                       // Position of the extremum.
                                                } else switch (ib3 % 3) {
                                                    case 0:  coordinate = envelope.getMinimum(dim); break;
                                                    case 1:  coordinate = envelope.getMaximum(dim); break;
                                                    case 2:  coordinate = envelope.getMedian (dim); break;
                                                    default: throw new AssertionError(ib3);     // Should never happen.
                                                }
                                                sourcePt[dim] = coordinate;
                                            }
                                            temporary = transform.transform(sourceView, temporary);
                                            transformed.add(temporary);
                                        }
                                    }
                                } while ((isP2 = !isP2) == true);
                            }
                        }
                    }
                }
                derivatives[pointIndex] = null;                 // Let GC do its job earlier.
            }
        }
        if (targetPt != null) {
            // Copy the coordinate of the center point.
            System.arraycopy(coordinates, coordinates.length - targetDim, targetPt, 0, targetDim);
        }
        return transformed;
    }

    /**
     * Transforms an envelope using the given coordinate operation.
     * The transformation is only approximated: the returned envelope may be bigger than the
     * smallest possible bounding box, but should not be smaller in most cases.
     *
     * <p>This method can handle the case where the envelope contains the North or South pole,
     * or when it cross the ±180° longitude.</p>
     *
     * <div class="note"><b>Note:</b>
     * If the envelope CRS is non-null, then the caller should ensure that the operation source CRS
     * is the same than the envelope CRS. In case of mismatch, this method transforms the envelope
     * to the operation source CRS before to apply the operation. This extra step may cause a lost
     * of accuracy. In order to prevent this method from performing such pre-transformation (if not desired),
     * callers can ensure that the envelope CRS is {@code null} before to call this method.</div>
     *
     * @param  operation  the operation to use.
     * @param  envelope   envelope to transform, or {@code null}. This envelope will not be modified.
     * @return the transformed envelope, or {@code null} if {@code envelope} was null.
     * @throws TransformException if a transform failed.
     *
     * @see #transform(MathTransform, Envelope)
     *
     * @since 0.5
     */
    @SuppressWarnings("null")
    public static GeneralEnvelope transform(final CoordinateOperation operation, Envelope envelope)
            throws TransformException
    {
        ArgumentChecks.ensureNonNull("operation", operation);
        if (envelope == null) {
            return null;
        }
        boolean isOperationComplete = true;
        final CoordinateReferenceSystem sourceCRS = operation.getSourceCRS();
        if (sourceCRS != null) {
            final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
            if (crs != null && !Utilities.equalsIgnoreMetadata(crs, sourceCRS)) {
                /*
                 * Argument-check: the envelope CRS seems inconsistent with the given operation.
                 * However we need to push the check a little bit further, since 3D-GeographicCRS
                 * are considered not equal to CompoundCRS[2D-GeographicCRS + ellipsoidal height].
                 * Checking for identity MathTransform is a more powerfull (but more costly) check.
                 * Since we have the MathTransform, perform an opportunist envelope transform if it
                 * happen to be required.
                 */
                final MathTransform mt;
                try {
                    mt = CoordinateOperations.factory().createOperation(crs, sourceCRS).getMathTransform();
                } catch (FactoryException e) {
                    throw new TransformException(Errors.format(Errors.Keys.CanNotTransformEnvelope), e);
                }
                if (!mt.isIdentity()) {
                    isOperationComplete = false;
                    envelope = transform(mt, envelope);
                }
            }
        }
        MathTransform mt = operation.getMathTransform();
        final double[] centerPt = new double[mt.getTargetDimensions()];
        final GeneralEnvelope transformed = transform(mt, envelope, centerPt);
        /*
         * If the source envelope crosses the expected range of valid coordinates, also projects
         * the range bounds as a safety. Example: if the source envelope goes from 150 to 200°E,
         * some map projections will interpret 200° as if it was -160°, and consequently produce
         * an envelope which do not include the 180°W extremum. We will add those extremum points
         * explicitly as a safety. It may leads to bigger than necessary target envelope, but the
         * contract is to include at least the source envelope, not to return the smallest one.
         */
        if (sourceCRS != null) {
            final CoordinateSystem cs = sourceCRS.getCoordinateSystem();
            if (cs != null) {                           // Should never be null, but check as a paranoiac safety.
                DirectPosition sourcePt = null;
                DirectPosition targetPt = null;
                final int dimension = cs.getDimension();
                for (int i=0; i<dimension; i++) {
                    final CoordinateSystemAxis axis = cs.getAxis(i);
                    if (axis == null) {                 // Should never be null, but check as a paranoiac safety.
                        continue;
                    }
                    final double min = envelope.getMinimum(i);
                    final double max = envelope.getMaximum(i);
                    final double  v1 = axis.getMinimumValue();
                    final double  v2 = axis.getMaximumValue();
                    final boolean b1 = (v1 > min && v1 < max);
                    final boolean b2 = (v2 > min && v2 < max);
                    if (!b1 && !b2) {
                        continue;
                    }
                    if (sourcePt == null) {
                        sourcePt = new GeneralDirectPosition(dimension);
                        for (int j=0; j<dimension; j++) {
                            sourcePt.setOrdinate(j, envelope.getMedian(j));
                        }
                    }
                    if (b1) {
                        sourcePt.setOrdinate(i, v1);
                        transformed.add(targetPt = mt.transform(sourcePt, targetPt));
                    }
                    if (b2) {
                        sourcePt.setOrdinate(i, v2);
                        transformed.add(targetPt = mt.transform(sourcePt, targetPt));
                    }
                    sourcePt.setOrdinate(i, envelope.getMedian(i));
                }
            }
        }
        /*
         * Now takes the target CRS in account...
         */
        final CoordinateReferenceSystem targetCRS = operation.getTargetCRS();
        if (targetCRS == null) {
            return transformed;
        }
        transformed.setCoordinateReferenceSystem(targetCRS);
        final CoordinateSystem targetCS = targetCRS.getCoordinateSystem();
        if (targetCS == null) {
            // It should be an error, but we keep this method tolerant.
            return transformed;
        }
        /*
         * Checks for singularity points. For example the south pole is a singularity point in
         * geographic CRS because is is located at the maximal value allowed by one particular
         * axis, namely latitude. This point is not a singularity in the stereographic projection,
         * because axes extends toward infinity in all directions (mathematically) and because the
         * South pole has nothing special apart being the origin (0,0).
         *
         * Algorithm:
         *
         * 1) Inspect the target axis, looking if there is any bounds. If bounds are found, get
         *    the coordinates of singularity points and project them from target to source CRS.
         *
         *    Example: If the transformed envelope above is (80 … 85°S, 10 … 50°W), and if the
         *             latitude in the target CRS is bounded at 90°S, then project (90°S, 30°W)
         *             to the source CRS. Note that the longitude is set to the the center of
         *             the envelope longitude range (more on this below).
         *
         * 2) If the singularity point computed above is inside the source envelope, add that
         *    point to the target (transformed) envelope.
         *
         * 3) If step #2 added the point, iterate over all other axes. If an other bounded axis
         *    is found and that axis is of kind "WRAPAROUND", test for inclusion the same point
         *    than the point tested at step #1, except for the coordinate of the axis found in
         *    this step. That coordinate is set to the minimal and maximal values of that axis.
         *
         *    Example: If the above steps found that the point (90°S, 30°W) need to be included,
         *             then this step #3 will also test the points (90°S, 180°W) and (90°S, 180°E).
         *
         * NOTE: we test (-180°, centerY), (180°, centerY), (centerX, -90°) and (centerX, 90°)
         * at step #1 before to test (-180°, -90°), (180°, -90°), (-180°, 90°) and (180°, 90°)
         * at step #3 because the later may not be supported by every projections. For example
         * if the target envelope is located between 20°N and 40°N, then a Mercator projection
         * may fail to transform the (-180°, 90°) coordinate while the (-180°, 30°) coordinate
         * is a valid point.
         */
        TransformException warning = null;
        AbstractEnvelope generalEnvelope = null;
        DirectPosition sourcePt = null;
        DirectPosition targetPt = null;
        long includedMinValue = 0;              // A bitmask for each dimension.
        long includedMaxValue = 0;
        long isWrapAroundAxis = 0;
        long dimensionBitMask = 1;
        final int dimension = targetCS.getDimension();
poles:  for (int i=0; i<dimension; i++, dimensionBitMask <<= 1) {
            final CoordinateSystemAxis axis = targetCS.getAxis(i);
            if (axis == null) {                 // Should never be null, but check as a paranoiac safety.
                continue;
            }
            boolean testMax = false;            // Tells if we are testing the minimal or maximal value.
            do {
                final double extremum = testMax ? axis.getMaximumValue() : axis.getMinimumValue();
                if (!Double.isFinite(extremum)) {
                    /*
                     * The axis is unbounded. It should always be the case when the target CRS is
                     * a map projection, in which case this loop will finish soon and this method
                     * will do nothing more (no object instantiated, no MathTransform inversed...)
                     */
                    continue;
                }
                if (targetPt == null) {
                    try {
                        mt = mt.inverse();
                    } catch (NoninvertibleTransformException exception) {
                        /*
                         * If the transform is non invertible, this method can't do anything. This
                         * is not a fatal error because the envelope has already be transformed by
                         * the caller. We lost the check for singularity points performed by this
                         * method, but it make no difference in the common case where the source
                         * envelope didn't contains any of those points.
                         *
                         * Note that this exception is normal if target dimension is smaller than
                         * source dimension, since the math transform can not reconstituate the
                         * lost dimensions. So we don't log any warning in this case.
                         */
                        if (dimension >= mt.getSourceDimensions()) {
                            warning = exception;
                        }
                        break poles;
                    }
                    targetPt = new GeneralDirectPosition(mt.getSourceDimensions());
                    for (int j=0; j<dimension; j++) {
                        targetPt.setOrdinate(j, centerPt[j]);
                    }
                    // TODO: avoid the hack below if we provide a contains(DirectPosition)
                    //       method in the GeoAPI org.opengis.geometry.Envelope interface.
                    generalEnvelope = AbstractEnvelope.castOrCopy(envelope);
                }
                targetPt.setOrdinate(i, extremum);
                try {
                    sourcePt = mt.transform(targetPt, sourcePt);
                } catch (TransformException exception) {
                    /*
                     * This exception may be normal. For example if may occur when projecting
                     * the latitude extremums with a cylindrical Mercator projection.  Do not
                     * log any message (unless logging level is fine) and try the other points.
                     */
                    if (warning == null) {
                        warning = exception;
                    } else {
                        warning.addSuppressed(exception);
                    }
                    continue;
                }
                if (generalEnvelope.contains(sourcePt)) {
                    transformed.add(targetPt);
                    if (testMax) includedMaxValue |= dimensionBitMask;
                    else         includedMinValue |= dimensionBitMask;
                }
            } while ((testMax = !testMax) == true);
            /*
             * Keep trace of axes of kind WRAPAROUND, except if the two extremum values of that
             * axis have been included in the envelope  (in which case the next step after this
             * loop doesn't need to be executed for that axis).
             */
            if ((includedMinValue & includedMaxValue & dimensionBitMask) == 0 && CoordinateOperations.isWrapAround(axis)) {
                isWrapAroundAxis |= dimensionBitMask;
            }
            // Restore 'targetPt' to its initial state, which is equals to 'centerPt'.
            if (targetPt != null) {
                targetPt.setOrdinate(i, centerPt[i]);
            }
        }
        /*
         * Step #3 described in the above "Algorithm" section: iterate over all dimensions
         * of type "WRAPAROUND" for which minimal or maximal axis values have not yet been
         * included in the envelope. The set of axes is specified by a bitmask computed in
         * the above loop.  We examine only the points that have not already been included
         * in the envelope.
         */
        final long includedBoundsValue = (includedMinValue | includedMaxValue);
        if (includedBoundsValue != 0) {
            while (isWrapAroundAxis != 0) {
                final int wrapAroundDimension = Long.numberOfTrailingZeros(isWrapAroundAxis);
                dimensionBitMask = 1 << wrapAroundDimension;
                isWrapAroundAxis &= ~dimensionBitMask;              // Clear now the bit, for the next iteration.
                final CoordinateSystemAxis wrapAroundAxis = targetCS.getAxis(wrapAroundDimension);
                final double min = wrapAroundAxis.getMinimumValue();
                final double max = wrapAroundAxis.getMaximumValue();
                /*
                 * Iterate over all axes for which a singularity point has been previously found,
                 * excluding the "wrap around axis" currently under consideration.
                 */
                for (long am=(includedBoundsValue & ~dimensionBitMask), bm; am != 0; am &= ~bm) {
                    bm = Long.lowestOneBit(am);
                    final int axisIndex = Long.numberOfTrailingZeros(bm);
                    final CoordinateSystemAxis axis = targetCS.getAxis(axisIndex);
                    /*
                     * switch (c) {
                     *   case 0: targetPt = (..., singularityMin, ..., wrapAroundMin, ...)
                     *   case 1: targetPt = (..., singularityMin, ..., wrapAroundMax, ...)
                     *   case 2: targetPt = (..., singularityMax, ..., wrapAroundMin, ...)
                     *   case 3: targetPt = (..., singularityMax, ..., wrapAroundMax, ...)
                     * }
                     */
                    for (int c=0; c<4; c++) {
                        /*
                         * Set the coordinate value along the axis having the singularity point
                         * (cases c=0 and c=2).  If the envelope did not included that point,
                         * then skip completely this case and the next one, i.e. skip c={0,1}
                         * or skip c={2,3}.
                         */
                        double value = max;
                        if ((c & 1) == 0) {         // 'true' if we are testing "wrapAroundMin".
                            if (((c == 0 ? includedMinValue : includedMaxValue) & bm) == 0) {
                                c++;                // Skip also the case for "wrapAroundMax".
                                continue;
                            }
                            targetPt.setOrdinate(axisIndex, (c == 0) ? axis.getMinimumValue() : axis.getMaximumValue());
                            value = min;
                        }
                        targetPt.setOrdinate(wrapAroundDimension, value);
                        try {
                            sourcePt = mt.transform(targetPt, sourcePt);
                        } catch (TransformException exception) {
                            if (warning == null) {
                                warning = exception;
                            } else {
                                warning.addSuppressed(exception);
                            }
                            continue;
                        }
                        if (generalEnvelope.contains(sourcePt)) {
                            transformed.add(targetPt);
                        }
                    }
                    targetPt.setOrdinate(axisIndex, centerPt[axisIndex]);
                }
                targetPt.setOrdinate(wrapAroundDimension, centerPt[wrapAroundDimension]);
            }
        }
        /*
         * At this point we finished envelope transformation. Verify if some coordinates need to be "wrapped around"
         * as a result of the coordinate operation.  This is usually the longitude axis where the source CRS uses
         * the [-180 … +180]° range and the target CRS uses the [0 … 360]° range, or the converse. We do not wrap
         * around if the source and target axes use the same range (e.g. the longitude stay [-180 … +180]°) in order
         * to reduce the risk of discontinuities. If the user really wants unconditional wrap around, (s)he can call
         * GeneralEnvelope.normalize().
         */
        final Set<Integer> wrapAroundChanges;
        if (isOperationComplete && operation instanceof AbstractCoordinateOperation) {
            wrapAroundChanges = ((AbstractCoordinateOperation) operation).getWrapAroundChanges();
        } else {
            wrapAroundChanges = CoordinateOperations.wrapAroundChanges(sourceCRS, targetCS);
        }
        transformed.normalize(targetCS, 0, wrapAroundChanges.size(), wrapAroundChanges.iterator());
        if (warning != null) {
            recoverableException(Envelopes.class, warning);
        }
        return transformed;
    }

    /**
     * Returns the bounding box of a geometry defined in <cite>Well Known Text</cite> (WKT) format.
     * This method does not check the consistency of the provided WKT. For example it does not check
     * that every points in a {@code LINESTRING} have the same dimension. However this method
     * ensures that the parenthesis are balanced, in order to catch some malformed WKT.
     *
     * <p>Example:</p>
     * <ul>
     *   <li>{@code BOX(-180 -90, 180 90)} (not really a geometry, but understood by many software products)</li>
     *   <li>{@code POINT(6 10)}</li>
     *   <li>{@code MULTIPOLYGON(((1 1, 5 1, 1 5, 1 1),(2 2, 3 2, 3 3, 2 2)))}</li>
     *   <li>{@code GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(3 8,7 10))}</li>
     * </ul>
     *
     * See {@link GeneralEnvelope#GeneralEnvelope(CharSequence)} for more information about the
     * parsing rules.
     *
     * @param  wkt  the {@code BOX}, {@code POLYGON} or other kind of element to parse.
     * @return the envelope of the given geometry.
     * @throws FactoryException if the given WKT can not be parsed.
     *
     * @see #toString(Envelope)
     * @see CRS#fromWKT(String)
     * @see org.apache.sis.io.wkt
     */
    public static Envelope fromWKT(final CharSequence wkt) throws FactoryException {
        ArgumentChecks.ensureNonNull("wkt", wkt);
        try {
            return new GeneralEnvelope(wkt);
        } catch (IllegalArgumentException e) {
            throw new FactoryException(Errors.format(
                    Errors.Keys.UnparsableStringForClass_2, Envelope.class), e);
        }
    }

    /**
     * Formats the given envelope as a {@code BOX} element. The output is like below,
     * where <var>n</var> is the {@linkplain Envelope#getDimension() number of dimensions}
     * (omitted if equals to 2):
     *
     * <blockquote>{@code BOX}<var>n</var>{@code D(}{@linkplain Envelope#getLowerCorner() lower
     * corner}{@code ,} {@linkplain Envelope#getUpperCorner() upper corner}{@code )}</blockquote>
     *
     * <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>
     *
     * The string returned by this method can be {@linkplain GeneralEnvelope#GeneralEnvelope(CharSequence)
     * parsed} by the {@code GeneralEnvelope} constructor.
     *
     * @param  envelope  the envelope to format.
     * @return this envelope as a {@code BOX} or {@code BOX3D} (most typical dimensions) element.
     *
     * @see #fromWKT(CharSequence)
     * @see org.apache.sis.io.wkt
     */
    public static String toString(final Envelope envelope) {
        return AbstractEnvelope.toString(envelope, false);
    }

    /**
     * Formats the given envelope as a {@code POLYGON} element in the <cite>Well Known Text</cite>
     * (WKT) format. {@code POLYGON} can be used as an alternative to {@code BOX} when the element
     * needs to be considered as a standard WKT geometry.
     *
     * <p>The string returned by this method can be {@linkplain GeneralEnvelope#GeneralEnvelope(CharSequence)
     * parsed} by the {@code GeneralEnvelope} constructor.</p>
     *
     * @param  envelope  the envelope to format.
     * @return the envelope as a {@code POLYGON} in WKT format.
     * @throws IllegalArgumentException if the given envelope can not be formatted.
     *
     * @see org.apache.sis.io.wkt
     */
    public static String toPolygonWKT(final Envelope envelope) throws IllegalArgumentException {
        /*
         * Get the dimension, ignoring the trailing ones which have infinite values.
         */
        int dimension = envelope.getDimension();
        while (dimension != 0) {
            final double length = envelope.getSpan(dimension - 1);
            if (Double.isFinite(length)) {
                break;
            }
            dimension--;
        }
        if (dimension < 2) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyEnvelope2D));
        }
        final StringBuilder buffer = new StringBuilder("POLYGON(");
        String separator = "(";
        for (int corner = 0; corner < CORNERS.length; corner += 2) {
            for (int i=0; i<dimension; i++) {
                final double value;
                switch (i) {
                    case  0: // Fall through
                    case  1: value = CORNERS[corner+i] ? envelope.getMaximum(i) : envelope.getMinimum(i); break;
                    default: value = envelope.getMedian(i); break;
                }
                trimFractionalPart(buffer.append(separator).append(value));
                separator = " ";
            }
            separator = ", ";
        }
        return buffer.append("))").toString();
    }

    /**
     * Enumeration of the 4 corners in an envelope, with repetition of the first point.
     * The values are (x,y) pairs with {@code false} meaning "minimal value" and {@code true}
     * meaning "maximal value". This is used by {@link #toPolygonWKT(Envelope)} only.
     */
    private static final boolean[] CORNERS = {
        false, false,
        false, true,
        true,  true,
        true,  false,
        false, false
    };
}
