You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2013/04/15 17:23:24 UTC

svn commit: r1468115 - in /sis/branches/JDK6: ./ sis-referencing/src/main/java/org/apache/sis/geometry/ sis-referencing/src/main/java/org/apache/sis/referencing/ sis-referencing/src/test/java/org/apache/sis/geometry/ sis-referencing/src/test/java/org/a...

Author: desruisseaux
Date: Mon Apr 15 15:23:24 2013
New Revision: 1468115

URL: http://svn.apache.org/r1468115
Log:
Merge from the JDK7 branch.

Added:
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
      - copied unchanged from r1467941, sis/branches/JDK7/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/SubEnvelope.java
      - copied unchanged from r1467941, sis/branches/JDK7/sis-referencing/src/main/java/org/apache/sis/geometry/SubEnvelope.java
    sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
      - copied unchanged from r1467941, sis/branches/JDK7/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
    sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/SubEnvelopeTest.java
      - copied unchanged from r1467941, sis/branches/JDK7/sis-referencing/src/test/java/org/apache/sis/geometry/SubEnvelopeTest.java
Modified:
    sis/branches/JDK6/   (props changed)
    sis/branches/JDK6/pom.xml
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractDirectPosition.java
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/Envelope2D.java
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ImmutableEnvelope.java
    sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
    sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java
    sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
    sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Static.java
    sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties

Propchange: sis/branches/JDK6/
------------------------------------------------------------------------------
  Merged /sis/branches/JDK7:r1467467-1467941

Modified: sis/branches/JDK6/pom.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/pom.xml?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/pom.xml (original)
+++ sis/branches/JDK6/pom.xml Mon Apr 15 15:23:24 2013
@@ -557,6 +557,7 @@ Apache SIS is a toolkit for describing l
           <docencoding>${website.encoding}</docencoding>        <!-- Encoding of the generated HTML files. -->
           <charset>${website.encoding}</charset>                <!-- Encoding to declare in the HTML META tag. -->
           <locale>${website.locale}</locale>                    <!-- Locale for navigation bar, help file contents, etc. -->
+          <author>false</author>                                <!-- Excludes the authors text in the generated docs. -->
           <version>false</version>                              <!-- Excludes the version text in the generated docs. -->
           <nosince>true</nosince>                               <!-- Omits the "Since" sections associated with the since tags. -->
           <noqualifier>all</noqualifier>                        <!-- Omit qualifying package name before class names in output. -->

Modified: sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractDirectPosition.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractDirectPosition.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractDirectPosition.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractDirectPosition.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -214,7 +214,7 @@ public abstract class AbstractDirectPosi
     }
 
     /**
-     * Implementation of the public {@link #toString()} and {@link Envelope2D#toString()} methods
+     * Implementation of the public {@link #toString()} and {@link DirectPosition2D#toString()} methods
      * for formatting a {@code POINT} element from a direct position in <cite>Well Known Text</cite>
      * (WKT) format.
      *

Modified: sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -915,20 +915,26 @@ public abstract class AbstractEnvelope i
     }
 
     /**
-     * Formats this envelope in the <cite>Well Known Text</cite> (WKT) format.
+     * 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}.
-     * Example:
+     * The number of dimension is written only if different than 2.
+     *
+     * <p>Example:</p>
      *
      * {@preformat wkt
+     *   BOX(-90 -180, 90 180)
      *   BOX3D(-90 -180 0, 90 180 1)
      * }
      *
+     * {@note The <code>BOX</code> element is not part of the standard <cite>Well Known Text</cite>
+     *        (WKT) format. However it is understood by many softwares, for example GDAL and PostGIS.}
+     *
      * The string returned by this method can be {@linkplain GeneralEnvelope#GeneralEnvelope(CharSequence) parsed}
      * by the {@code GeneralEnvelope} constructor.
      *
-     * @return This envelope as a {@code BOX2D} or {@code BOX3D} (most typical dimensions) in WKT format.
+     * @return This envelope as a {@code BOX} or {@code BOX3D} (most typical dimensions) element.
      */
     @Override
     public String toString() {
@@ -936,12 +942,12 @@ public abstract class AbstractEnvelope i
     }
 
     /**
-     * Implementation of the public {@link #toString()} and {@link Envelopes#toWKT(Envelope)} methods
-     * for formatting a {@code BOX} element from an envelope in <cite>Well Known Text</cite> (WKT) format.
+     * 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  isSimplePrecision {@code true} if every lower and upper corner values can be casted to {@code float}.
-     * @return The envelope as a {@code BOX2D} or {@code BOX3D} (most typical dimensions) in WKT format.
+     * @return This envelope as a {@code BOX} or {@code BOX3D} (most typical dimensions) element.
      *
      * @see GeneralEnvelope#GeneralEnvelope(CharSequence)
      * @see org.apache.sis.measure.CoordinateFormat
@@ -949,7 +955,10 @@ public abstract class AbstractEnvelope i
      */
     static String toString(final Envelope envelope, final boolean isSimplePrecision) {
         final int dimension = envelope.getDimension();
-        final StringBuilder buffer = new StringBuilder(64).append("BOX").append(dimension).append('D');
+        final StringBuilder buffer = new StringBuilder(64).append("BOX");
+        if (dimension != 2) {
+            buffer.append(dimension).append('D');
+        }
         if (dimension == 0) {
             buffer.append("()");
         } else {

Modified: sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -45,8 +45,16 @@ import org.apache.sis.internal.jdk7.Obje
 
 
 /**
- * Base class of envelopes backed by an array.
- * See {@link GeneralEnvelope} javadoc for more information.
+ * Base class of envelopes backed by an array. The ordinate values are stored in the {@link #ordinates} array.
+ * The ordinate values of the lower corner are stored in the array portion from index {@link #beginIndex()}
+ * inclusive to index {@link #endIndex()} exclusive. The ordinate values of the upper corner are stored in
+ * the array portion from index {@code beginIndex() + d} inclusive to index {@code endIndex() + d} exclusive
+ * where {@code d = ordinates.length >>> 1}.
+ *
+ * <p>Unless otherwise indicated by a "{@code // Must be overridden in SubEnvelope}" comment, every methods
+ * in {@code ArrayEnvelope} and subclasses must take in account the {@code beginIndex} and {@code endIndex}
+ * bounds. A few methods ignore the bounds for performance reason, so they need a dedicated implementation
+ * in {@link SubEnvelope}.</p>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3 (derived from geotk-2.4)
@@ -60,9 +68,9 @@ class ArrayEnvelope extends AbstractEnve
     private static final long serialVersionUID = 1657970968782634545L;
 
     /**
-     * Ordinate values of lower and upper corners. The length of this array is twice the
-     * number of dimensions. The first half contains the lower corner, while the second
-     * half contains the upper corner.
+     * Ordinate values of lower and upper corners. Except for {@link SubEnvelope}, the length of
+     * this array is twice the number of dimensions. The first half contains the lower corner,
+     * while the second half contains the upper corner.
      */
     final double[] ordinates;
 
@@ -72,6 +80,17 @@ class ArrayEnvelope extends AbstractEnve
     CoordinateReferenceSystem crs;
 
     /**
+     * Creates a new envelope using the given array of ordinate values. This constructor stores
+     * the given reference directly; it does <strong>not</strong> clone the given array. This is
+     * the desired behavior for proper working of {@link SubEnvelope}.
+     *
+     * @param ordinates The array of ordinate values to store directly (not cloned).
+     */
+    ArrayEnvelope(final double[] ordinates) {
+        this.ordinates = ordinates;
+    }
+
+    /**
      * Constructs an envelope defined by two corners given as direct positions.
      * If at least one corner is associated to a CRS, then the new envelope will also
      * be associated to that CRS.
@@ -140,20 +159,14 @@ class ArrayEnvelope extends AbstractEnve
      */
     public ArrayEnvelope(final Envelope envelope) {
         ensureNonNull("envelope", envelope);
-        if (envelope instanceof ArrayEnvelope) {
-            final ArrayEnvelope e = (ArrayEnvelope) envelope;
-            ordinates = e.ordinates.clone();
-            crs = e.crs;
-        } else {
-            crs = envelope.getCoordinateReferenceSystem();
-            final int dimension = envelope.getDimension();
-            ordinates = new double[dimension * 2];
-            final DirectPosition lowerCorner = envelope.getLowerCorner();
-            final DirectPosition upperCorner = envelope.getUpperCorner();
-            for (int i=0; i<dimension; i++) {
-                ordinates[i]           = lowerCorner.getOrdinate(i);
-                ordinates[i+dimension] = upperCorner.getOrdinate(i);
-            }
+        crs = envelope.getCoordinateReferenceSystem();
+        final int dimension = envelope.getDimension();
+        ordinates = new double[dimension * 2];
+        final DirectPosition lowerCorner = envelope.getLowerCorner();
+        final DirectPosition upperCorner = envelope.getUpperCorner();
+        for (int i=0; i<dimension; i++) {
+            ordinates[i]           = lowerCorner.getOrdinate(i);
+            ordinates[i+dimension] = upperCorner.getOrdinate(i);
         }
     }
 
@@ -187,8 +200,8 @@ class ArrayEnvelope extends AbstractEnve
 
     /**
      * Constructs a new envelope initialized to the values parsed from the given string in
-     * <cite>Well Known Text</cite> (WKT) format. The given string is typically a {@code BOX}
-     * element like below:
+     * {@code BOX} or <cite>Well Known Text</cite> (WKT) format. The given string is typically
+     * a {@code BOX} element like below:
      *
      * {@preformat wkt
      *     BOX(-180 -90, 180 90)
@@ -313,14 +326,47 @@ scanNumber: while ((i += Character.charC
     }
 
     /**
+     * Returns the index of the first valid ordinate value of the lower corner in the {@link #ordinates} array.
+     * This is always 0, unless this envelope is a {@link SubEnvelope}.
+     *
+     * <p>See {@link #endIndex()} for the list of methods that need to be also overridden
+     * if this {@code beginIndex()} method is overridden.</p>
+     */
+    int beginIndex() {
+        return 0;
+    }
+
+    /**
+     * Returns the index after the last valid ordinate value of the lower corner in the {@link #ordinates} array.
+     * This is always {@code ordinates.length >>> 1}, unless this envelope is a {@link SubEnvelope}.
+     *
+     * <p>Unless otherwise indicated by a "{@code // Must be overridden in SubEnvelope}" comment, every methods
+     * in {@code ArrayEnvelope} and subclasses must take in account the {@code beginIndex} and {@code endIndex}
+     * bounds. The methods listed below ignore the bounds for performance reason, so they need to be overridden
+     * in {@link SubEnvelope}:</p>
+     *
+     * <ul>
+     *   <li>{@link #getDimension()}</li>
+     *   <li>{@link #getLower(int)}</li>
+     *   <li>{@link #getUpper(int)}</li>
+     *   <li>{@link #isAllNaN()}</li>
+     *   <li>{@link #hashCode()}</li>
+     *   <li>{@link #equals(Object)}</li>
+     * </ul>
+     */
+    int endIndex() {
+        return ordinates.length >>> 1;
+    }
+
+    /**
      * Returns the length of coordinate sequence (the number of entries) in this envelope.
      * This information is available even when the {@linkplain #getCoordinateReferenceSystem()
      * coordinate reference system} is unknown.
      *
      * @return The dimensionality of this envelope.
      */
-    @Override
-    public final int getDimension() {
+    @Override // Must also be overridden in SubEnvelope
+    public int getDimension() {
         return ordinates.length >>> 1;
     }
 
@@ -332,7 +378,7 @@ scanNumber: while ((i += Character.charC
      * @return The envelope CRS, or {@code null} if unknown.
      */
     @Override
-    public final CoordinateReferenceSystem getCoordinateReferenceSystem() {
+    public CoordinateReferenceSystem getCoordinateReferenceSystem() {
         assert crs == null || crs.getCoordinateSystem().getDimension() == getDimension();
         return crs;
     }
@@ -340,7 +386,7 @@ scanNumber: while ((i += Character.charC
     /**
      * {@inheritDoc}
      */
-    @Override
+    @Override // Must also be overridden in SubEnvelope
     public double getLower(final int dimension) throws IndexOutOfBoundsException {
         ensureValidIndex(ordinates.length >>> 1, dimension);
         return ordinates[dimension];
@@ -349,11 +395,11 @@ scanNumber: while ((i += Character.charC
     /**
      * {@inheritDoc}
      */
-    @Override
+    @Override // Must also be overridden in SubEnvelope
     public double getUpper(final int dimension) throws IndexOutOfBoundsException {
-        final int dim = ordinates.length >>> 1;
-        ensureValidIndex(dim, dimension);
-        return ordinates[dimension + dim];
+        final int d = ordinates.length >>> 1;
+        ensureValidIndex(d, dimension);
+        return ordinates[dimension + d];
     }
 
     /**
@@ -361,10 +407,10 @@ scanNumber: while ((i += Character.charC
      */
     @Override
     public double getMinimum(final int dimension) throws IndexOutOfBoundsException {
-        final int dim = ordinates.length >>> 1;
-        ensureValidIndex(dim, dimension);
-        double lower = ordinates[dimension];
-        if (isNegative(ordinates[dimension + dim] - lower)) { // Special handling for -0.0
+        ensureValidIndex(endIndex(), dimension);
+        final int i = dimension + beginIndex();
+        double lower = ordinates[i];
+        if (isNegative(ordinates[i + (ordinates.length >>> 1)] - lower)) { // Special handling for -0.0
             final CoordinateSystemAxis axis = getAxis(crs, dimension);
             lower = (axis != null) ? axis.getMinimumValue() : Double.NEGATIVE_INFINITY;
         }
@@ -376,10 +422,10 @@ scanNumber: while ((i += Character.charC
      */
     @Override
     public double getMaximum(final int dimension) throws IndexOutOfBoundsException {
-        final int dim = ordinates.length >>> 1;
-        ensureValidIndex(dim, dimension);
-        double upper = ordinates[dimension + dim];
-        if (isNegative(upper - ordinates[dimension])) { // Special handling for -0.0
+        ensureValidIndex(endIndex(), dimension);
+        final int i = dimension + beginIndex();
+        double upper = ordinates[i + (ordinates.length >>> 1)];
+        if (isNegative(upper - ordinates[i])) { // Special handling for -0.0
             final CoordinateSystemAxis axis = getAxis(crs, dimension);
             upper = (axis != null) ? axis.getMaximumValue() : Double.POSITIVE_INFINITY;
         }
@@ -391,9 +437,10 @@ scanNumber: while ((i += Character.charC
      */
     @Override
     public double getMedian(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(ordinates.length >>> 1, dimension);
-        final double minimum = ordinates[dimension];
-        final double maximum = ordinates[dimension + (ordinates.length >>> 1)];
+        ensureValidIndex(endIndex(), dimension);
+        final int i = dimension + beginIndex();
+        final double minimum = ordinates[i];
+        final double maximum = ordinates[i + (ordinates.length >>> 1)];
         double median = 0.5 * (minimum + maximum);
         if (isNegative(maximum - minimum)) { // Special handling for -0.0
             median = fixMedian(getAxis(crs, dimension), median);
@@ -406,8 +453,9 @@ scanNumber: while ((i += Character.charC
      */
     @Override
     public double getSpan(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(ordinates.length >>> 1, dimension);
-        double span = ordinates[dimension + (ordinates.length >>> 1)] - ordinates[dimension];
+        ensureValidIndex(endIndex(), dimension);
+        final int i = dimension + beginIndex();
+        double span = ordinates[i + (ordinates.length >>> 1)] - ordinates[i];
         if (isNegative(span)) { // Special handling for -0.0
             span = fixSpan(getAxis(crs, dimension), span);
         }
@@ -419,14 +467,16 @@ scanNumber: while ((i += Character.charC
      */
     @Override
     public boolean isEmpty() {
-        final int dimension = ordinates.length >>> 1;
-        if (dimension == 0) {
+        final int beginIndex = beginIndex();
+        final int endIndex = endIndex();
+        if (beginIndex == endIndex) {
             return true;
         }
-        for (int i=0; i<dimension; i++) {
-            final double span = ordinates[i+dimension] - ordinates[i];
+        final int d = ordinates.length >>> 1;
+        for (int i=beginIndex; i<endIndex; i++) {
+            final double span = ordinates[i+d] - ordinates[i];
             if (!(span > 0)) { // Use '!' in order to catch NaN
-                if (!(isNegative(span) && isWrapAround(crs, i))) {
+                if (!(isNegative(span) && isWrapAround(crs, i - beginIndex))) {
                     return true;
                 }
             }
@@ -438,7 +488,7 @@ scanNumber: while ((i += Character.charC
     /**
      * {@inheritDoc}
      */
-    @Override
+    @Override // Must also be overridden in SubEnvelope
     public boolean isAllNaN() {
         for (int i=0; i<ordinates.length; i++) {
             if (!Double.isNaN(ordinates[i])) {
@@ -452,20 +502,28 @@ scanNumber: while ((i += Character.charC
     /**
      * {@inheritDoc}
      */
-    @Override
+    @Override // Must also be overridden in SubEnvelope
     public int hashCode() {
         int code = Arrays.hashCode(ordinates);
         if (crs != null) {
             code += crs.hashCode();
         }
-        assert code == super.hashCode();
+        assert code == hashCodeByAPI();
         return code;
     }
 
     /**
+     * Computes the hash code value using the public API instead than direct access to the
+     * {@link #ordinates} array. This method is invoked from {@link SubEnvelope}.
+     */
+    final int hashCodeByAPI() {
+        return super.hashCode();
+    }
+
+    /**
      * {@inheritDoc}
      */
-    @Override
+    @Override // Must also be overridden in SubEnvelope
     public boolean equals(final Object object) {
         if (object != null && object.getClass() == getClass()) {
             final ArrayEnvelope that = (ArrayEnvelope) object;
@@ -476,6 +534,14 @@ scanNumber: while ((i += Character.charC
     }
 
     /**
+     * Compares the given object for equality using the public API instead than direct access
+     * to the {@link #ordinates} array. This method is invoked from {@link SubEnvelope}.
+     */
+    final boolean equalsByAPI(final Object object) {
+        return super.equals(object);
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override

Modified: sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/Envelope2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/Envelope2D.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/Envelope2D.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/Envelope2D.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -196,7 +196,7 @@ public class Envelope2D extends Rectangl
              box.getSouthBoundLatitude(),
              box.getEastBoundLongitude(),
              box.getNorthBoundLatitude());
-        if (false) try { // TODO: excluded for now because CRS.forCode is not yet implemented.
+        try {
             crs = CRS.forCode("CRS:84");
         } catch (FactoryException e) {
             // Should never happen since we asked for a CRS which should always be present.
@@ -966,16 +966,16 @@ public class Envelope2D extends Rectangl
     }
 
     /**
-     * Formats this envelope in the <cite>Well Known Text</cite> (WKT) format.
-     * The output is of the form "{@code BOX2D(}{@linkplain #getLowerCorner()
+     * Formats this envelope as a "{@code BOX}" element.
+     * The output is of the form "{@code BOX(}{@linkplain #getLowerCorner()
      * lower corner}{@code ,}{@linkplain #getUpperCorner() upper corner}{@code )}".
      * Example:
      *
      * {@preformat wkt
-     *   BOX3D(-90 -180, 90 180)
+     *   BOX(-90 -180, 90 180)
      * }
      *
-     * @see Envelopes#toWKT(Envelope)
+     * @see Envelopes#toString(Envelope)
      */
     @Override
     public String toString() {

Modified: sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -62,7 +62,7 @@ import static org.apache.sis.math.MathFu
  *   <li>{@linkplain #GeneralEnvelope(Envelope) From a an other envelope} (copy constructor).</li>
  *   <li>{@linkplain #GeneralEnvelope(GeographicBoundingBox) From a geographic bounding box}.</li>
  *   <li>{@linkplain #GeneralEnvelope(CharSequence) From a character sequence}
- *       representing a {@code BBOX} in <cite>Well Known Text</cite> (WKT) format.</li>
+ *       representing a {@code BBOX} or a <cite>Well Known Text</cite> (WKT) format.</li>
  * </ul>
  *
  * {@section Spanning the anti-meridian of a Geographic CRS}
@@ -112,6 +112,17 @@ public class GeneralEnvelope extends Arr
     private static volatile Field ordinatesField;
 
     /**
+     * Creates a new envelope using the given array of ordinate values. This constructor stores
+     * the given reference directly; it does <strong>not</strong> clone the given array. This is
+     * the desired behavior for proper working of {@link SubEnvelope}.
+     *
+     * @param ordinates The array of ordinate values to store directly (not cloned).
+     */
+    GeneralEnvelope(final double[] ordinates) {
+        super(ordinates);
+    }
+
+    /**
      * Constructs an envelope defined by two corners given as direct positions.
      * If at least one corner is associated to a CRS, then the new envelope will also
      * be associated to that CRS.
@@ -182,8 +193,8 @@ public class GeneralEnvelope extends Arr
 
     /**
      * Constructs a new envelope initialized to the values parsed from the given string in
-     * <cite>Well Known Text</cite> (WKT) format. The given string is typically a {@code BOX}
-     * element like below:
+     * {@code BOX} or <cite>Well Known Text</cite> (WKT) format. The given string is typically
+     * a {@code BOX} element like below:
      *
      * {@preformat wkt
      *     BOX(-180 -90, 180 90)
@@ -201,11 +212,11 @@ public class GeneralEnvelope extends Arr
      *   <li>The coordinate having the highest dimension determines the dimension of this envelope.</li>
      * </ul>
      *
-     * This constructor does not check the consistency of the provided WKT. For example it doesn't
+     * This constructor does not check the consistency of the provided text. For example it does not
      * check that every points in a {@code LINESTRING} have the same dimension. However this
      * constructor ensures that the parenthesis are balanced, in order to catch some malformed WKT.
      *
-     * <p>The following examples can be parsed by this constructor in addition of the standard
+     * <p>The following examples can be parsed by this constructor in addition of the usual
      * {@code BOX} element. This constructor creates the bounding box of those geometries:</p>
      *
      * <ul>
@@ -217,8 +228,8 @@ public class GeneralEnvelope extends Arr
      * @param  wkt The {@code BOX}, {@code POLYGON} or other kind of element to parse.
      * @throws IllegalArgumentException If the given string can not be parsed.
      *
-     * @see Envelopes#parseWKT(String)
-     * @see Envelopes#toWKT(Envelope)
+     * @see Envelopes#fromWKT(String)
+     * @see Envelopes#toString(Envelope)
      */
     public GeneralEnvelope(final CharSequence wkt) throws IllegalArgumentException {
         super(wkt);
@@ -270,7 +281,7 @@ public class GeneralEnvelope extends Arr
      * @param  upper     The limit in the direction of increasing ordinate values.
      * @throws IndexOutOfBoundsException If the given index is out of bounds.
      */
-    @Override
+    @Override // Must also be overridden in SubEnvelope
     public void setRange(final int dimension, final double lower, final double upper)
             throws IndexOutOfBoundsException
     {
@@ -283,27 +294,37 @@ public class GeneralEnvelope extends Arr
     /**
      * Sets the envelope to the specified values, which must be the lower corner coordinates
      * followed by upper corner coordinates. The number of arguments provided shall be twice
-     * this {@linkplain #getDimension envelope dimension}, and minimum shall not be greater
+     * this {@linkplain #getDimension() envelope dimension}, and minimum shall not be greater
      * than maximum.
      *
      * <p><b>Example:</b></p>
      * (<var>x</var><sub>min</sub>, <var>y</var><sub>min</sub>, <var>z</var><sub>min</sub>,
      *  <var>x</var><sub>max</sub>, <var>y</var><sub>max</sub>, <var>z</var><sub>max</sub>)
      *
-     * @param ordinates The new ordinate values.
+     * @param corners Ordinates of the new lower corner followed by the new upper corner.
      */
-    public void setEnvelope(final double... ordinates) {
-        if ((ordinates.length & 1) != 0) {
+    public void setEnvelope(final double... corners) {
+        verifyArrayLength(ordinates.length >>> 1, corners);
+        System.arraycopy(corners, 0, ordinates, 0, ordinates.length);
+    }
+
+    /**
+     * Verifies that the given array of ordinate values has the expected length
+     * for the given number of dimensions.
+     *
+     * @param dimension The dimension of the envelope.
+     * @param corners The user-provided array of ordinate values.
+     */
+    static void verifyArrayLength(final int dimension, final double[] corners) {
+        if ((corners.length & 1) != 0) {
             throw new IllegalArgumentException(Errors.format(
-                    Errors.Keys.OddArrayLength_1, ordinates.length));
+                    Errors.Keys.OddArrayLength_1, corners.length));
         }
-        final int dimension = ordinates.length >>> 1;
-        final int expected  = this.ordinates.length >>> 1;
-        if (dimension != expected) {
+        final int d = corners.length >>> 1;
+        if (d != dimension) {
             throw new MismatchedDimensionException(Errors.format(
-                    Errors.Keys.MismatchedDimension_3, "ordinates", expected, dimension));
+                    Errors.Keys.MismatchedDimension_3, "ordinates", dimension, d));
         }
-        System.arraycopy(ordinates, 0, this.ordinates, 0, ordinates.length);
     }
 
     /**
@@ -317,17 +338,17 @@ public class GeneralEnvelope extends Arr
      */
     public void setEnvelope(final Envelope envelope) throws MismatchedDimensionException {
         ensureNonNull("envelope", envelope);
-        final int dimension = ordinates.length >>> 1;
+        final int beginIndex = beginIndex();
+        final int dimension = endIndex() - beginIndex;
         ensureDimensionMatches("envelope", dimension, envelope);
-        if (envelope instanceof ArrayEnvelope) {
-            System.arraycopy(((ArrayEnvelope) envelope).ordinates, 0, ordinates, 0, ordinates.length);
-        } else {
-            final DirectPosition lower = envelope.getLowerCorner();
-            final DirectPosition upper = envelope.getUpperCorner();
-            for (int i=0; i<dimension; i++) {
-                ordinates[i]           = lower.getOrdinate(i);
-                ordinates[i+dimension] = upper.getOrdinate(i);
-            }
+        final DirectPosition lower = envelope.getLowerCorner();
+        final DirectPosition upper = envelope.getUpperCorner();
+        final int d = ordinates.length >>> 1;
+        for (int i=0; i<dimension; i++) {
+            final int iLower = beginIndex + i;
+            final int iUpper = iLower + d;
+            ordinates[iLower] = lower.getOrdinate(i);
+            ordinates[iUpper] = upper.getOrdinate(i);
         }
         final CoordinateReferenceSystem envelopeCRS = envelope.getCoordinateReferenceSystem();
         if (envelopeCRS != null) {
@@ -344,9 +365,11 @@ public class GeneralEnvelope extends Arr
      * (if any) stay unchanged.
      */
     public void setToInfinite() {
-        final int mid = ordinates.length >>> 1;
-        Arrays.fill(ordinates, 0,   mid,              Double.NEGATIVE_INFINITY);
-        Arrays.fill(ordinates, mid, ordinates.length, Double.POSITIVE_INFINITY);
+        final int beginIndex = beginIndex();
+        final int endIndex = endIndex();
+        final int d = ordinates.length >>> 1;
+        Arrays.fill(ordinates, beginIndex,   endIndex,   Double.NEGATIVE_INFINITY);
+        Arrays.fill(ordinates, beginIndex+d, endIndex+d, Double.POSITIVE_INFINITY);
     }
 
     /**
@@ -356,6 +379,7 @@ public class GeneralEnvelope extends Arr
      *
      * @see #isAllNaN()
      */
+    // Must be overridden in SubEnvelope
     public void setToNaN() {
         Arrays.fill(ordinates, Double.NaN);
         assert isAllNaN() : this;
@@ -369,12 +393,12 @@ public class GeneralEnvelope extends Arr
      * @param  array The array which contains the ordinate values.
      * @param  offset Index of the first valid ordinate value in the given array.
      */
-    final void add(final double[] array, final int offset) {
-        final int dim = ordinates.length >>> 1;
-        for (int i=0; i<dim; i++) {
+    final void addSimple(final double[] array, final int offset) {
+        final int d = ordinates.length >>> 1;
+        for (int i=0; i<d; i++) {
             final double value = array[offset + i];
-            if (value < ordinates[i    ]) ordinates[i    ] = value;
-            if (value > ordinates[i+dim]) ordinates[i+dim] = value;
+            if (value < ordinates[i  ]) ordinates[i  ] = value;
+            if (value > ordinates[i+d]) ordinates[i+d] = value;
         }
     }
 
@@ -407,23 +431,27 @@ public class GeneralEnvelope extends Arr
      */
     public void add(final DirectPosition position) throws MismatchedDimensionException {
         ensureNonNull("position", position);
-        final int dim = ordinates.length >>> 1;
-        ensureDimensionMatches("position", dim, position);
+        final int beginIndex = beginIndex();
+        final int dimension = endIndex() - beginIndex;
+        ensureDimensionMatches("position", dimension, position);
         assert equalsIgnoreMetadata(crs, position.getCoordinateReferenceSystem(), true) : position;
-        for (int i=0; i<dim; i++) {
+        final int d = ordinates.length >>> 1;
+        for (int i=0; i<dimension; i++) {
+            final int iLower = beginIndex + i;
+            final int iUpper = iLower + d;
             final double value = position.getOrdinate(i);
-            final double min = ordinates[i];
-            final double max = ordinates[i+dim];
+            final double min = ordinates[iLower];
+            final double max = ordinates[iUpper];
             if (!isNegative(max - min)) { // Standard case, or NaN.
-                if (value < min) ordinates[i    ] = value;
-                if (value > max) ordinates[i+dim] = value;
+                if (value < min) ordinates[iLower] = value;
+                if (value > max) ordinates[iUpper] = value;
             } else {
                 /*
                  * Spanning the anti-meridian. The [max…min] range (not that min/max are
                  * interchanged) is actually an exclusion area. Changes only the closest
                  * side.
                  */
-                addToClosest(i, value, max, min);
+                addToClosest(iLower, value, max, min);
             }
         }
         assert contains(position) || isEmpty() || hasNaN(position) : position;
@@ -477,14 +505,18 @@ public class GeneralEnvelope extends Arr
      */
     public void add(final Envelope envelope) throws MismatchedDimensionException {
         ensureNonNull("envelope", envelope);
-        final int dim = ordinates.length >>> 1;
-        ensureDimensionMatches("envelope", dim, envelope);
+        final int beginIndex = beginIndex();
+        final int dimension = endIndex() - beginIndex;
+        ensureDimensionMatches("envelope", dimension, envelope);
         assert equalsIgnoreMetadata(crs, envelope.getCoordinateReferenceSystem(), true) : envelope;
         final DirectPosition lower = envelope.getLowerCorner();
         final DirectPosition upper = envelope.getUpperCorner();
-        for (int i=0; i<dim; i++) {
-            final double min0 = ordinates[i];
-            final double max0 = ordinates[i+dim];
+        final int d = ordinates.length >>> 1;
+        for (int i=0; i<dimension; i++) {
+            final int iLower = beginIndex + i;
+            final int iUpper = iLower + d;
+            final double min0 = ordinates[iLower];
+            final double max0 = ordinates[iUpper];
             final double min1 = lower.getOrdinate(i);
             final double max1 = upper.getOrdinate(i);
             final boolean sp0 = isNegative(max0 - min0);
@@ -504,9 +536,9 @@ public class GeneralEnvelope extends Arr
                  *    ──┘ │  │ └──          ────┼──┼─┘└─
                  *    ────┘  └────          ────┘  └────
                  */
-                if (min1 < min0) ordinates[i    ] = min1;
-                if (max1 > max0) ordinates[i+dim] = max1;
-                if (!sp0 || isNegativeUnsafe(ordinates[i+dim] - ordinates[i])) {
+                if (min1 < min0) ordinates[iLower] = min1;
+                if (max1 > max0) ordinates[iUpper] = max1;
+                if (!sp0 || isNegativeUnsafe(ordinates[iUpper] - ordinates[iLower])) {
                     continue; // We are done, go to the next dimension.
                 }
                 // If we were spanning the anti-meridian before the union but
@@ -539,8 +571,8 @@ public class GeneralEnvelope extends Arr
                 if (left > 0 || right > 0) {
                     // The < and > checks below are not completly redundant.
                     // The difference is when a value is NaN.
-                    if (left > right) ordinates[i    ] = min1;
-                    if (right > left) ordinates[i+dim] = max1; // This is the case illustrated above.
+                    if (left > right) ordinates[iLower] = min1;
+                    if (right > left) ordinates[iUpper] = max1; // This is the case illustrated above.
                     continue; // We are done, go to the next dimension.
                 }
                 // If we reach this point, the given envelope fills completly the "exclusion area"
@@ -552,15 +584,15 @@ public class GeneralEnvelope extends Arr
                  * given envelope spans to infinities.
                  */
                 if (max0 <= max1 || min0 >= min1) {
-                    ordinates[i]     = min1;
-                    ordinates[i+dim] = max1;
+                    ordinates[iLower]   = min1;
+                    ordinates[iUpper] = max1;
                     continue;
                 }
                 final double left  = min0 - max1;
                 final double right = min1 - max0;
                 if (left > 0 || right > 0) {
-                    if (left > right) ordinates[i+dim] = max1;
-                    if (right > left) ordinates[i    ] = min1;
+                    if (left > right) ordinates[iUpper] = max1;
+                    if (right > left) ordinates[iLower] = min1;
                     continue;
                 }
             }
@@ -570,11 +602,11 @@ public class GeneralEnvelope extends Arr
              * the "normal" / "anti-meridian spanning" state.
              */
             if (sp0) {
-                ordinates[i    ] = +0.0;
-                ordinates[i+dim] = -0.0;
+                ordinates[iLower] = +0.0;
+                ordinates[iUpper] = -0.0;
             } else {
-                ordinates[i    ] = Double.NEGATIVE_INFINITY;
-                ordinates[i+dim] = Double.POSITIVE_INFINITY;
+                ordinates[iLower] = Double.NEGATIVE_INFINITY;
+                ordinates[iUpper] = Double.POSITIVE_INFINITY;
             }
         }
         assert contains(envelope, true) || isEmpty() || hasNaN(envelope) : this;
@@ -596,14 +628,18 @@ public class GeneralEnvelope extends Arr
      */
     public void intersect(final Envelope envelope) throws MismatchedDimensionException {
         ensureNonNull("envelope", envelope);
-        final int dim = ordinates.length >>> 1;
-        ensureDimensionMatches("envelope", dim, envelope);
+        final int beginIndex = beginIndex();
+        final int dimension = endIndex() - beginIndex;
+        ensureDimensionMatches("envelope", dimension, envelope);
         assert equalsIgnoreMetadata(crs, envelope.getCoordinateReferenceSystem(), true) : envelope;
         final DirectPosition lower = envelope.getLowerCorner();
         final DirectPosition upper = envelope.getUpperCorner();
-        for (int i=0; i<dim; i++) {
-            final double min0  = ordinates[i];
-            final double max0  = ordinates[i+dim];
+        final int d = ordinates.length >>> 1;
+        for (int i=beginIndex; i<dimension; i++) {
+            final int iLower = beginIndex + i;
+            final int iUpper = iLower + d;
+            final double min0  = ordinates[iLower];
+            final double max0  = ordinates[iUpper];
             final double min1  = lower.getOrdinate(i);
             final double max1  = upper.getOrdinate(i);
             final double span0 = max0 - min0;
@@ -632,7 +668,7 @@ public class GeneralEnvelope extends Arr
                      *   │    │     └────┘
                      *   └────┘
                      */
-                    ordinates[i] = ordinates[i+dim] = Double.NaN;
+                    ordinates[iLower] = ordinates[iUpper] = Double.NaN;
                     continue;
                 }
             } else {
@@ -647,8 +683,8 @@ public class GeneralEnvelope extends Arr
                          *       └─┼────┘ │                     └────┘  │  │
                          *    ─────┘      └─────              ──────────┘  └─────
                          */
-                        if (min1 <= max0) {intersect  = 1; ordinates[i    ] = min1;}
-                        if (max1 >= min0) {intersect |= 2; ordinates[i+dim] = max1;}
+                        if (min1 <= max0) {intersect  = 1; ordinates[iLower] = min1;}
+                        if (max1 >= min0) {intersect |= 2; ordinates[iUpper] = max1;}
                     } else {
                         // Same than above, but with indices 0 and 1 interchanged.
                         // No need to set ordinate values since they would be the same.
@@ -673,8 +709,8 @@ public class GeneralEnvelope extends Arr
                  */
                 switch (intersect) {
                     default: throw new AssertionError(intersect);
-                    case 1: if (max1 < max0) ordinates[i+dim] = max1; break;
-                    case 2: if (min1 > min0) ordinates[i    ] = min1; break;
+                    case 1: if (max1 < max0) ordinates[iUpper] = max1; break;
+                    case 2: if (min1 > min0) ordinates[iLower] = min1; break;
                     case 3: // Fall through
                     case 0: {
                         // Before to declare the intersection as invalid, verify if the envelope
@@ -692,15 +728,15 @@ public class GeneralEnvelope extends Arr
                             min = Double.NaN;
                             max = Double.NaN;
                         }
-                        ordinates[i]     = min;
-                        ordinates[i+dim] = max;
+                        ordinates[iLower] = min;
+                        ordinates[iUpper] = max;
                         break;
                     }
                 }
                 continue;
             }
-            if (min1 > min0) ordinates[i    ] = min1;
-            if (max1 < max0) ordinates[i+dim] = max1;
+            if (min1 > min0) ordinates[iLower] = min1;
+            if (max1 < max0) ordinates[iUpper] = max1;
         }
         // Tests only if the interection result is non-empty.
         assert isEmpty() || AbstractEnvelope.castOrCopy(envelope).contains(this, true) : this;
@@ -762,22 +798,25 @@ public class GeneralEnvelope extends Arr
     public boolean normalize() {
         boolean changed = false;
         if (crs != null) {
-            final int dimension = ordinates.length >>> 1;
+            final int d = ordinates.length >>> 1;
+            final int beginIndex = beginIndex();
+            final int dimension = endIndex() - beginIndex;
             final CoordinateSystem cs = crs.getCoordinateSystem();
             for (int i=0; i<dimension; i++) {
-                final int j = i + dimension;
+                final int iLower = beginIndex + i;
+                final int iUpper = iLower + d;
                 final CoordinateSystemAxis axis = cs.getAxis(i);
                 final double  minimum = axis.getMinimumValue();
                 final double  maximum = axis.getMaximumValue();
                 final RangeMeaning rm = axis.getRangeMeaning();
                 if (RangeMeaning.EXACT.equals(rm)) {
-                    if (ordinates[i] < minimum) {ordinates[i] = minimum; changed = true;}
-                    if (ordinates[j] > maximum) {ordinates[j] = maximum; changed = true;}
+                    if (ordinates[iLower] < minimum) {ordinates[iLower] = minimum; changed = true;}
+                    if (ordinates[iUpper] > maximum) {ordinates[iUpper] = maximum; changed = true;}
                 } else if (RangeMeaning.WRAPAROUND.equals(rm)) {
                     final double csSpan = maximum - minimum;
                     if (csSpan > 0 && csSpan < Double.POSITIVE_INFINITY) {
-                        double o1 = ordinates[i];
-                        double o2 = ordinates[j];
+                        double o1 = ordinates[iLower];
+                        double o2 = ordinates[iUpper];
                         if (Math.abs(o2-o1) >= csSpan) {
                             /*
                              * If the range exceed the CS span, then we have to replace it by the
@@ -790,19 +829,19 @@ public class GeneralEnvelope extends Arr
                              */
                             if (o1 != minimum || o2 != maximum) {
                                 if ((o1 % csSpan) == 0 && (o2 % csSpan) == 0) {
-                                    ordinates[i] = +0.0;
-                                    ordinates[j] = -0.0;
+                                    ordinates[iLower] = +0.0;
+                                    ordinates[iUpper] = -0.0;
                                 } else {
-                                    ordinates[i] = minimum;
-                                    ordinates[j] = maximum;
+                                    ordinates[iLower] = minimum;
+                                    ordinates[iUpper] = maximum;
                                 }
                                 changed = true;
                             }
                         } else {
                             o1 = Math.floor((o1 - minimum) / csSpan) * csSpan;
                             o2 = Math.floor((o2 - minimum) / csSpan) * csSpan;
-                            if (o1 != 0) {ordinates[i] -= o1; changed = true;}
-                            if (o2 != 0) {ordinates[j] -= o2; changed = true;}
+                            if (o1 != 0) {ordinates[iLower] -= o1; changed = true;}
+                            if (o2 != 0) {ordinates[iUpper] -= o2; changed = true;}
                         }
                     }
                 }
@@ -836,16 +875,19 @@ public class GeneralEnvelope extends Arr
      */
     public boolean simplify() throws IllegalStateException {
         boolean changed = false;
-        final int dimension = ordinates.length >>> 1;
+        final int d = ordinates.length >>> 1;
+        final int beginIndex = beginIndex();
+        final int dimension = endIndex() - beginIndex;
         for (int i=0; i<dimension; i++) {
-            final int j = i+dimension;
-            final double lower = ordinates[i];
-            final double upper = ordinates[j];
+            final int iLower = beginIndex + i;
+            final int iUpper = iLower + d;
+            final double lower = ordinates[iLower];
+            final double upper = ordinates[iUpper];
             if (isNegative(upper - lower)) {
                 final CoordinateSystemAxis axis = getAxis(crs, i);
                 if (axis != null && RangeMeaning.WRAPAROUND.equals(axis.getRangeMeaning())) {
-                    ordinates[i] = axis.getMinimumValue();
-                    ordinates[j] = axis.getMaximumValue();
+                    ordinates[iLower] = axis.getMinimumValue();
+                    ordinates[iUpper] = axis.getMaximumValue();
                     changed = true;
                 } else {
                     throw new IllegalStateException(Errors.format(Errors.Keys.IllegalOrdinateRange_3,
@@ -857,6 +899,41 @@ public class GeneralEnvelope extends Arr
     }
 
     /**
+     * Returns a view over this envelope that encompass only some dimensions. The returned object is "live":
+     * changes applied on the original envelope is reflected in the sub-envelope view, and conversely.
+     *
+     * <p>This method is useful for querying and updating only some dimensions.
+     * For example in order to expand only the horizontal component of a four dimensional
+     * (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>) envelope, one can use:</p>
+     *
+     * {@preformat
+     *     envelope.subEnvelope(0, 2).add(myPosition2D);
+     * }
+     *
+     * If the sub-envelope needs to be independent from the original envelope, use the following idiom:
+     *
+     * {@preformat
+     *     GeneralEnvelope copy = envelope.subEnvelope(0, 2).clone();
+     * }
+     *
+     * The sub-envelope is initialized with a {@code null} {@linkplain #getCoordinateReferenceSystem() CRS}.
+     * This method does not compute a sub-CRS because it may not be needed, or the sub-CRS may be already
+     * known by the caller.
+     *
+     * @param  beginIndex The index of the first valid ordinate value of the corners.
+     * @param  endIndex   The index after the last valid ordinate value of the corners.
+     * @return The sub-envelope of dimension {@code endIndex - beginIndex}.
+     * @throws IndexOutOfBoundsException If an index is out of bounds.
+     */
+    // Must be overridden in SubEnvelope
+    public GeneralEnvelope subEnvelope(final int beginIndex, final int endIndex) throws IndexOutOfBoundsException {
+        ensureValidIndexRange(ordinates.length >>> 1, beginIndex, endIndex);
+        return new SubEnvelope(ordinates, beginIndex, endIndex);
+        // Do check if we could return "this" as an optimization, in order to keep the
+        // method contract simpler (i.e. the returned envelope CRS is always null).
+    }
+
+    /**
      * Returns a deep copy of this envelope.
      *
      * @return A clone of this envelope.

Modified: sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ImmutableEnvelope.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ImmutableEnvelope.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ImmutableEnvelope.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/geometry/ImmutableEnvelope.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -136,8 +136,8 @@ public final class ImmutableEnvelope ext
 
     /**
      * Constructs a new envelope initialized to the values parsed from the given string in
-     * <cite>Well Known Text</cite> (WKT) format. The given string is typically a {@code BOX}
-     * element like below:
+     * {@code BOX} or <cite>Well Known Text</cite> (WKT) format. The given string is typically
+     * a {@code BOX} element like below:
      *
      * {@preformat wkt
      *     BOX(-180 -90, 180 90)

Modified: sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -54,6 +54,6 @@ public final class CRS extends Static {
             throws NoSuchAuthorityCodeException, FactoryException
     {
         ensureNonNull("code", code);
-        throw new UnsupportedOperationException("Not yet implemented.");
+        return null;
     }
 }

Modified: sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractEnvelopeTest.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -50,7 +50,7 @@ public final strictfp class AbstractEnve
      * Enumeration of implementations to be tested.
      * The {@code LAST} constant is for stopping the loops.
      */
-    private static final int GENERAL=0, IMMUTABLE=1, RECTANGLE=2, LAST=3;
+    private static final int GENERAL=0, IMMUTABLE=1, RECTANGLE=2, SUBENVELOPE=3, LAST=4;
 
     /**
      * The coordinate reference system used for the tests.
@@ -85,6 +85,17 @@ public final strictfp class AbstractEnve
                 envelope = new Envelope2D(WGS84, xmin, ymin, xmax - xmin, ymax - ymin);
                 break;
             }
+            case SUBENVELOPE: {
+                final GeneralEnvelope ge = new GeneralEnvelope(5);
+                ge.setCoordinateReferenceSystem(WGS84);
+                ge.setRange(1, xmin, xmax);
+                ge.setRange(2, ymin, ymax);
+                ge.setRange(0, 2, 3); // Following values will be verified in verifyInvariants(…)
+                ge.setRange(3, 4, 6);
+                ge.setRange(4, 8, 9);
+                envelope = ge.subEnvelope(1, 3);
+                break;
+            }
             default: throw new IllegalArgumentException(String.valueOf(type));
         }
         if (PENDING_NEXT_GEOAPI_RELEASE) {
@@ -94,6 +105,26 @@ public final strictfp class AbstractEnve
     }
 
     /**
+     * Verifies some invariants for the given envelope of the given type.
+     */
+    private static void verifyInvariants(final int type, final Envelope envelope) {
+        assertSame(WGS84, envelope.getCoordinateReferenceSystem());
+        switch (type) {
+            case SUBENVELOPE: {
+                // Asserts that other dimensions in the original envelope has not been modified.
+                final double[] ordinates = ((SubEnvelope) envelope).ordinates;
+                assertEquals(2, ordinates[0], STRICT);
+                assertEquals(3, ordinates[5], STRICT);
+                assertEquals(4, ordinates[3], STRICT);
+                assertEquals(6, ordinates[8], STRICT);
+                assertEquals(8, ordinates[4], STRICT);
+                assertEquals(9, ordinates[9], STRICT);
+                break;
+            }
+        }
+    }
+
+    /**
      * Tests the simple case (no anti-meridian crossing).
      *
      * {@preformat text
@@ -121,24 +152,29 @@ public final strictfp class AbstractEnve
             assertEquals(label, 12, envelope.getMaximum(0), STRICT);
             assertEquals(label,  4, envelope.getMedian (0), STRICT);
             assertEquals(label, 16, envelope.getSpan   (0), STRICT);
-            if (envelope instanceof AbstractEnvelope) {
-                final AbstractEnvelope ext = (AbstractEnvelope) envelope;
-                assertTrue (label, ext.contains  (inside));
-                assertFalse(label, ext.contains  (outside));
-                assertFalse(label, ext.contains  (intersect, false));
-                assertTrue (label, ext.intersects(intersect, false));
-                assertDisjoint(ext, disjoint);
-                assertContains(ext, contained);
-            }
-            if (envelope instanceof Rectangle2D) {
-                final Rectangle2D ext = (Rectangle2D) envelope;
-                assertTrue (label, ext.contains  (inside));
-                assertFalse(label, ext.contains  (outside));
-                assertFalse(label, ext.contains  (intersect));
-                assertTrue (label, ext.intersects(intersect));
-                assertDisjoint(ext, disjoint);
-                assertContains(ext, contained);
+            switch (type) {
+                default: {
+                    final AbstractEnvelope ext = (AbstractEnvelope) envelope;
+                    assertTrue (label, ext.contains  (inside));
+                    assertFalse(label, ext.contains  (outside));
+                    assertFalse(label, ext.contains  (intersect, false));
+                    assertTrue (label, ext.intersects(intersect, false));
+                    assertDisjoint(ext, disjoint);
+                    assertContains(ext, contained);
+                    break;
+                }
+                case RECTANGLE: {
+                    final Rectangle2D ext = (Rectangle2D) envelope;
+                    assertTrue (label, ext.contains  (inside));
+                    assertFalse(label, ext.contains  (outside));
+                    assertFalse(label, ext.contains  (intersect));
+                    assertTrue (label, ext.intersects(intersect));
+                    assertDisjoint(ext, disjoint);
+                    assertContains(ext, contained);
+                    break;
+                }
             }
+            verifyInvariants(type, envelope);
         }
     }
 
@@ -176,26 +212,31 @@ public final strictfp class AbstractEnve
             assertEquals(label, +180, envelope.getMaximum (0), STRICT);
             assertEquals(label, -176, envelope.getMedian  (0), STRICT);
             assertEquals(label,  344, envelope.getSpan    (0), STRICT); // 360° - testSimpleEnvelope()
-            if (envelope instanceof AbstractEnvelope) {
-                final AbstractEnvelope ext = (AbstractEnvelope) envelope;
-                assertTrue (label, ext.contains  (inside));
-                assertFalse(label, ext.contains  (outside));
-                assertFalse(label, ext.contains  (intersect, false));
-                assertTrue (label, ext.intersects(intersect, false));
-                assertDisjoint(ext, disjoint);
-                assertContains(ext, contained);
-                assertContains(ext, spanning);
-            }
-            if (envelope instanceof Rectangle2D) {
-                final Rectangle2D ext = (Rectangle2D) envelope;
-                assertTrue (label, ext.contains  (inside));
-                assertFalse(label, ext.contains  (outside));
-                assertFalse(label, ext.contains  (intersect));
-                assertTrue (label, ext.intersects(intersect));
-                assertDisjoint(ext, disjoint);
-                assertContains(ext, contained);
-                assertContains(ext, spanning);
+            switch (type) {
+                default: {
+                    final AbstractEnvelope ext = (AbstractEnvelope) envelope;
+                    assertTrue (label, ext.contains  (inside));
+                    assertFalse(label, ext.contains  (outside));
+                    assertFalse(label, ext.contains  (intersect, false));
+                    assertTrue (label, ext.intersects(intersect, false));
+                    assertDisjoint(ext, disjoint);
+                    assertContains(ext, contained);
+                    assertContains(ext, spanning);
+                    break;
+                }
+                case RECTANGLE: {
+                    final Rectangle2D ext = (Rectangle2D) envelope;
+                    assertTrue (label, ext.contains  (inside));
+                    assertFalse(label, ext.contains  (outside));
+                    assertFalse(label, ext.contains  (intersect));
+                    assertTrue (label, ext.intersects(intersect));
+                    assertDisjoint(ext, disjoint);
+                    assertContains(ext, contained);
+                    assertContains(ext, spanning);
+                    break;
+                }
             }
+            verifyInvariants(type, envelope);
         }
     }
 
@@ -244,6 +285,7 @@ public final strictfp class AbstractEnve
                 assertTrue (label, ext.intersects(spanning,  false));
                 assertDisjoint(ext, disjoint);
                 assertContains(ext, contained);
+                break;
             }
             if (envelope instanceof Rectangle2D) {
                 final Rectangle2D ext = (Rectangle2D) envelope;
@@ -255,7 +297,9 @@ public final strictfp class AbstractEnve
                 assertTrue (label, ext.intersects(spanning));
                 assertDisjoint(ext, disjoint);
                 assertContains(ext, contained);
+                break;
             }
+            verifyInvariants(type, envelope);
         }
     }
 
@@ -287,26 +331,31 @@ public final strictfp class AbstractEnve
             assertEquals(label, +180, envelope.getMaximum (0), STRICT);
             assertEquals(label, -176, envelope.getMedian  (0), STRICT); // Note the alternance with the previous test methods.
             assertEquals(label,  NaN, envelope.getSpan    (0), STRICT); // testCrossingAntiMeridianTwice() + 360°.
-            if (envelope instanceof AbstractEnvelope) {
-                final AbstractEnvelope ext = (AbstractEnvelope) envelope;
-                assertFalse(label, ext.contains  (wasInside));
-                assertFalse(label, ext.contains  (outside));
-                assertFalse(label, ext.contains  (spanning,  false));
-                assertTrue (label, ext.intersects(spanning,  false));
-                assertDisjoint(ext, wasIntersect);
-                assertDisjoint(ext, disjoint);
-                assertDisjoint(ext, wasContained);
-            }
-            if (envelope instanceof Rectangle2D) {
-                final Rectangle2D ext = (Rectangle2D) envelope;
-                assertFalse(label, ext.contains  (wasInside));
-                assertFalse(label, ext.contains  (outside));
-                assertFalse(label, ext.contains  (spanning));
-                assertTrue (label, ext.intersects(spanning));
-                assertDisjoint(ext, wasIntersect);
-                assertDisjoint(ext, disjoint);
-                assertDisjoint(ext, wasContained);
+            switch (type) {
+                default: {
+                    final AbstractEnvelope ext = (AbstractEnvelope) envelope;
+                    assertFalse(label, ext.contains  (wasInside));
+                    assertFalse(label, ext.contains  (outside));
+                    assertFalse(label, ext.contains  (spanning,  false));
+                    assertTrue (label, ext.intersects(spanning,  false));
+                    assertDisjoint(ext, wasIntersect);
+                    assertDisjoint(ext, disjoint);
+                    assertDisjoint(ext, wasContained);
+                    break;
+                }
+                case RECTANGLE: {
+                    final Rectangle2D ext = (Rectangle2D) envelope;
+                    assertFalse(label, ext.contains  (wasInside));
+                    assertFalse(label, ext.contains  (outside));
+                    assertFalse(label, ext.contains  (spanning));
+                    assertTrue (label, ext.intersects(spanning));
+                    assertDisjoint(ext, wasIntersect);
+                    assertDisjoint(ext, disjoint);
+                    assertDisjoint(ext, wasContained);
+                    break;
+                }
             }
+            verifyInvariants(type, envelope);
         }
     }
 
@@ -331,28 +380,33 @@ public final strictfp class AbstractEnve
             assertEquals(label,  0.0, envelope.getMaximum(0), STRICT);
             assertEquals(label,    0, envelope.getMedian (0), STRICT);
             assertEquals(label,    0, envelope.getSpan   (0), STRICT);
-            if (envelope instanceof AbstractEnvelope) {
-                final AbstractEnvelope ext = (AbstractEnvelope) envelope;
-                assertFalse(label, ext.contains  (wasInside));
-                assertFalse(label, ext.contains  (outside));
-                assertFalse(label, ext.contains  (intersect, false));
-                assertTrue (label, ext.intersects(intersect, false));
-                assertFalse(label, ext.contains  (spanning,  false));
-                assertFalse(label, ext.intersects(spanning,  false));
-                assertFalse(label, ext.intersects(spanning,  false));
-                assertDisjoint(ext, wasContained);
-            }
-            if (envelope instanceof Rectangle2D) {
-                final Rectangle2D ext = (Rectangle2D) envelope;
-                assertFalse(label, ext.contains  (wasInside));
-                assertFalse(label, ext.contains  (outside));
-                assertFalse(label, ext.contains  (intersect));
-                assertTrue (label, ext.intersects(intersect));
-                assertFalse(label, ext.contains  (spanning));
-                assertFalse(label, ext.intersects(spanning));
-                assertFalse(label, ext.intersects(spanning));
-                assertDisjoint(ext, wasContained);
+            switch (type) {
+                default: {
+                    final AbstractEnvelope ext = (AbstractEnvelope) envelope;
+                    assertFalse(label, ext.contains  (wasInside));
+                    assertFalse(label, ext.contains  (outside));
+                    assertFalse(label, ext.contains  (intersect, false));
+                    assertTrue (label, ext.intersects(intersect, false));
+                    assertFalse(label, ext.contains  (spanning,  false));
+                    assertFalse(label, ext.intersects(spanning,  false));
+                    assertFalse(label, ext.intersects(spanning,  false));
+                    assertDisjoint(ext, wasContained);
+                    break;
+                }
+                case RECTANGLE: {
+                    final Rectangle2D ext = (Rectangle2D) envelope;
+                    assertFalse(label, ext.contains  (wasInside));
+                    assertFalse(label, ext.contains  (outside));
+                    assertFalse(label, ext.contains  (intersect));
+                    assertTrue (label, ext.intersects(intersect));
+                    assertFalse(label, ext.contains  (spanning));
+                    assertFalse(label, ext.intersects(spanning));
+                    assertFalse(label, ext.intersects(spanning));
+                    assertDisjoint(ext, wasContained);
+                    break;
+                }
             }
+            verifyInvariants(type, envelope);
         }
     }
 
@@ -382,22 +436,27 @@ public final strictfp class AbstractEnve
             assertEquals(label, +180, envelope.getMaximum (0), STRICT);
             assertEquals(label,  180, envelope.getMedian  (0), STRICT);
             assertEquals(label,  360, envelope.getSpan    (0), STRICT);
-            if (envelope instanceof AbstractEnvelope) {
-                final AbstractEnvelope ext = (AbstractEnvelope) envelope;
-                assertTrue(label, ext.contains(inside));
-                assertTrue(label, ext.contains(wasOutside));
-                assertTrue(label, ext.intersects(intersect, false));
-                assertContains(ext, contained);
-                assertContains(ext, spanning);
-            }
-            if (envelope instanceof Rectangle2D) {
-                final Rectangle2D ext = (Rectangle2D) envelope;
-                assertTrue(label, ext.contains(inside));
-                assertTrue(label, ext.contains(wasOutside));
-                assertTrue(label, ext.intersects(intersect));
-                assertContains(ext, contained);
-                assertContains(ext, spanning);
+            switch (type) {
+                default: {
+                    final AbstractEnvelope ext = (AbstractEnvelope) envelope;
+                    assertTrue(label, ext.contains(inside));
+                    assertTrue(label, ext.contains(wasOutside));
+                    assertTrue(label, ext.intersects(intersect, false));
+                    assertContains(ext, contained);
+                    assertContains(ext, spanning);
+                    break;
+                }
+                case RECTANGLE: {
+                    final Rectangle2D ext = (Rectangle2D) envelope;
+                    assertTrue(label, ext.contains(inside));
+                    assertTrue(label, ext.contains(wasOutside));
+                    assertTrue(label, ext.intersects(intersect));
+                    assertContains(ext, contained);
+                    assertContains(ext, spanning);
+                    break;
+                }
             }
+            verifyInvariants(type, envelope);
         }
     }
 }

Modified: sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -43,11 +43,11 @@ import static org.apache.sis.geometry.Ab
  * @module
  */
 @DependsOn(AbstractEnvelopeTest.class)
-public final strictfp class GeneralEnvelopeTest extends TestCase {
+public strictfp class GeneralEnvelopeTest extends TestCase {
     /**
      * The comparison threshold for strict comparisons.
      */
-    private static final double STRICT = 0;
+    static final double STRICT = 0;
 
     /**
      * Tolerance threshold for floating point comparisons.
@@ -56,8 +56,9 @@ public final strictfp class GeneralEnvel
 
     /**
      * Creates a new geographic envelope for the given ordinate values.
+     * This method is overridden by {@link SubEnvelopeTest}.
      */
-    private static GeneralEnvelope create(final double xmin, final double ymin, final double xmax, final double ymax) {
+    GeneralEnvelope create(final double xmin, final double ymin, final double xmax, final double ymax) {
         final GeneralEnvelope envelope = new GeneralEnvelope(2);
         envelope.setCoordinateReferenceSystem(WGS84);
         envelope.setEnvelope(xmin, ymin, xmax, ymax);
@@ -68,6 +69,14 @@ public final strictfp class GeneralEnvel
     }
 
     /**
+     * Verifies invariants for the given envelope after each test.
+     * This method is overridden by {@link SubEnvelopeTest}.
+     */
+    void verifyInvariants(final GeneralEnvelope envelope) {
+        assertSame(WGS84, envelope.getCoordinateReferenceSystem());
+    }
+
+    /**
      * Asserts that the given two-dimensional envelope is equals to the given rectangle.
      * The {@code xLower} and {@code xUpper} arguments are the <var>x</var> ordinate values
      * for the lower and upper corners respectively. The actual {@code xmin} and {@code ymin}
@@ -263,6 +272,10 @@ public final strictfp class GeneralEnvel
         //  ─────┘     └─────
         e2.setRange(0, 10, 90);
         assertIntersectEquals(e1, e2, NaN, ymin, NaN, ymax);
+
+        // Post-test verification, mostly for SubEnvelope.
+        verifyInvariants(e1);
+        verifyInvariants(e2);
     }
 
     /**
@@ -324,6 +337,10 @@ public final strictfp class GeneralEnvel
         //  ─────┘     └─────
         e2.setRange(0, 10, 90);
         assertUnionEquals(e1, e2, +0.0, ymin, -0.0, ymax, true, true);
+
+        // Post-test verification, mostly for SubEnvelope.
+        verifyInvariants(e1);
+        verifyInvariants(e2);
     }
 
     /**
@@ -353,6 +370,8 @@ public final strictfp class GeneralEnvel
 
         p.x = 30; // Add on the left side.
         assertAddEquals(e, p, 80, ymin, 30, ymax);
+
+        verifyInvariants(e);
     }
 
     /**
@@ -377,6 +396,7 @@ public final strictfp class GeneralEnvel
         assertTrue(e.normalize());
         assertEquals("Expect positive zero", Double.doubleToLongBits(+0.0), Double.doubleToLongBits(e.getLower(0)));
         assertEquals("Expect negative zero", Double.doubleToLongBits(-0.0), Double.doubleToLongBits(e.getUpper(0)));
+        verifyInvariants(e);
     }
 
     /**
@@ -389,6 +409,7 @@ public final strictfp class GeneralEnvel
         GeneralEnvelope e = create(-195, -90, +170, +90); // -195° is equivalent to 165°
         assertTrue(e.normalize());
         assertEnvelopeEquals(e, -180, -90, +180, +90);
+        verifyInvariants(e);
     }
 
     /**
@@ -411,6 +432,7 @@ public final strictfp class GeneralEnvel
         e = create(0.0, -10, -0.0, 10);
         assertTrue(e.simplify());
         assertEnvelopeEquals(e, -180, -10, 180, 10);
+        verifyInvariants(e);
     }
 
     /**
@@ -425,6 +447,7 @@ public final strictfp class GeneralEnvel
         assertEquals(-2.0, e.getLower(1), 0.0);
         assertEquals( 3.0, e.getUpper(0), 0.0);
         assertEquals(-1.0, e.getUpper(1), 0.0);
+        verifyInvariants(e);
     }
 
     /**
@@ -457,20 +480,20 @@ public final strictfp class GeneralEnvel
         assertEquals(  40, envelope.getUpper(1), STRICT);
         validate(envelope);
 
-        assertEquals("BOX2D(6 10, 6 10)",     new GeneralEnvelope("POINT(6 10)").toString());
+        assertEquals("BOX(6 10, 6 10)",     new GeneralEnvelope("POINT(6 10)").toString());
         assertEquals("BOX3D(6 10 3, 6 10 3)", new GeneralEnvelope("POINT M [ 6 10 3 ] ").toString());
-        assertEquals("BOX2D(3 4, 20 50)",     new GeneralEnvelope("LINESTRING(3 4,10 50,20 25)").toString());
-        assertEquals("BOX2D(1 1, 6 5)",       new GeneralEnvelope(
+        assertEquals("BOX(3 4, 20 50)",     new GeneralEnvelope("LINESTRING(3 4,10 50,20 25)").toString());
+        assertEquals("BOX(1 1, 6 5)",       new GeneralEnvelope(
                 "MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2, 3 2, 3 3, 2 3,2 2)),((3 3,6 2,6 4,3 3)))").toString());
-        assertEquals("BOX2D(3 6, 7 10)", new GeneralEnvelope("GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(3 8,7 10))").toString());
+        assertEquals("BOX(3 6, 7 10)", new GeneralEnvelope("GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(3 8,7 10))").toString());
         assertEquals(0, new GeneralEnvelope("BOX()").getDimension());
 
         try {
-            new GeneralEnvelope("BOX2D(3 4");
+            new GeneralEnvelope("BOX(3 4");
             fail("Parsing should fails because of missing parenthesis.");
         } catch (IllegalArgumentException e) {
             // This is the expected exception.
-            assertTrue(e.getMessage().contains("BOX2D"));
+            assertTrue(e.getMessage().contains("BOX"));
         }
         try {
             new GeneralEnvelope("LINESTRING(3 4,10 50),20 25)");
@@ -574,10 +597,8 @@ public final strictfp class GeneralEnvel
      * Tests {@code GeneralEnvelope} serialization.
      */
     @Test
-    public void testSerialization() {
-        final GeneralEnvelope e1 = new GeneralEnvelope(
-                new double[] {-20, -10},
-                new double[] { 20,  10});
+    public final void testSerialization() {
+        final GeneralEnvelope e1 = create(-20, -10, 20, 10);
         final GeneralEnvelope e2 = assertSerializedEquals(e1);
         assertNotSame(e1, e2);
         validate(e2);

Modified: sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -35,6 +35,7 @@ import org.junit.runners.Suite;
     org.apache.sis.geometry.DirectPosition2DTest.class,
     org.apache.sis.geometry.AbstractEnvelopeTest.class,
     org.apache.sis.geometry.GeneralEnvelopeTest.class,
+    org.apache.sis.geometry.SubEnvelopeTest.class,
     org.apache.sis.geometry.ImmutableEnvelopeTest.class,
     org.apache.sis.geometry.Envelope2DTest.class
 })

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Static.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Static.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Static.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Static.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -51,6 +51,8 @@ package org.apache.sis.util;
  * <tr><th colspan="2" class="hsep">OGC/ISO objects (metadata, referencing, geometries)</th></tr>
  * <tr><td>{@link org.apache.sis.metadata.iso.extent.Extents}</td>
  *     <td>Extract information from {@link org.opengis.metadata.extent.Extent} objects.</td></tr>
+ * <tr><td>{@link org.apache.sis.geometry.Envelopes}</td>
+ *     <td>Parse, format and transform {@linkplain org.opengis.geometry.Envelope envelopes}.</td></tr>
  *
  * <tr><th colspan="2" class="hsep">Input / Output (including CRS, XML, images)</th></tr>
  * <tr><td>{@link org.apache.sis.io.IO}</td>

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Mon Apr 15 15:23:24 2013
@@ -139,6 +139,11 @@ public final class Errors extends Indexe
         public static final int EmptyDictionary = 54;
 
         /**
+         * Envelope must be at least two-dimensional and non-empty.
+         */
+        public static final int EmptyEnvelope2D = 88;
+
+        /**
          * Property named “{0}” shall not be empty.
          */
         public static final int EmptyProperty_1 = 55;

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Mon Apr 15 15:23:24 2013
@@ -39,6 +39,7 @@ DuplicatedValuesCount_1         = Found 
 ElementAlreadyPresent_1         = Element \u201c{0}\u201d is already present.
 EmptyArgument_1                 = Argument \u2018{0}\u2019 shall not be empty.
 EmptyDictionary                 = The dictionary shall contains at least one entry.
+EmptyEnvelope2D                 = Envelope must be at least two-dimensional and non-empty.
 EmptyProperty_1                 = Property named \u201c{0}\u201d shall not be empty.
 ExcessiveArgumentSize_3         = Argument \u2018{0}\u2019 shall not contain more than {1} elements. A number of {2} is excessive.
 ForbiddenAttribute_2            = Attribute \u201c{0}\u201d is not allowed for an object of type \u2018{1}\u2019.

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1468115&r1=1468114&r2=1468115&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Mon Apr 15 15:23:24 2013
@@ -29,6 +29,7 @@ DuplicatedValuesCount_1         = {0} va
 ElementAlreadyPresent_1         = L\u2019\u00e9lement \u201c{0}\u201d est d\u00e9j\u00e0 pr\u00e9sent.
 EmptyArgument_1                 = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre vide.
 EmptyDictionary                 = Le dictionnaire doit contenir au moins une entr\u00e9e.
+EmptyEnvelope2D                 = L\u2019enveloppe doit avoir au moins deux dimensions et ne pas \u00eatre vide.
 EmptyProperty_1                 = La propri\u00e9t\u00e9 nomm\u00e9e \u201c{0}\u201d ne doit pas \u00eatre vide.
 ExcessiveArgumentSize_3         = L\u2019argument \u2018{0}\u2019 ne peut pas contenir plus de {1} \u00e9l\u00e9ments. Un nombre de {2} est excessif.
 ForbiddenAttribute_2            = L\u2019attribut \u201c{0}\u201d n\u2019est pas autoris\u00e9 pour un objet de type \u2018{1}\u2019.