sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1693912 [1/3] - in /sis/trunk: ./ core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ core/sis-metadata/src/main/java/org/apache/sis/io/wkt/ core/sis-metadata/src/main/java/org/apache/sis/metadata/ core/sis-metad...
Date Mon, 03 Aug 2015 14:46:31 GMT
Author: desruisseaux
Date: Mon Aug  3 14:46:30 2015
New Revision: 1693912

URL: http://svn.apache.org/r1693912
Log:
Merge from the JDK6 branch.

Added:
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
      - copied unchanged from r1693911, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
      - copied unchanged from r1693911, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
      - copied, changed from r1693911, sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
Removed:
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConformal.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java
Modified:
    sis/trunk/   (props changed)
    sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java
    sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
    sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
    sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java
    sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java
    sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
    sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java
    sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/test/MetadataAssert.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConformalProjection.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
    sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderMock.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ProjectionResultComparator.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java
    sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/simple/SimpleIdentifiedObject.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/DefaultFactories.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Numbers.java
    sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/NilObjectHandler.java
    sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
    sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/util/NumericsTest.java
    sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java
    sis/trunk/ide-project/NetBeans/nbproject/project.properties

Propchange: sis/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Aug  3 14:46:30 2015
@@ -1,4 +1,4 @@
 /sis/branches/Android:1430670-1480699
-/sis/branches/JDK6:1394364-1692168
-/sis/branches/JDK7:1394913-1692163
-/sis/branches/JDK8:1584960-1692159
+/sis/branches/JDK6:1394364-1693911
+/sis/branches/JDK7:1394913-1693908
+/sis/branches/JDK8:1584960-1693906

Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -108,7 +108,7 @@ public class ReferenceSystemMetadata ext
     public boolean equals(final Object object, final ComparisonMode mode) {
         if (super.equals(object, mode) && (object instanceof ReferenceSystem)) {
             final ReferenceSystem that = (ReferenceSystem) object;
-            if (mode.ordinal() >= ComparisonMode.IGNORE_METADATA.ordinal()) {
+            if (mode.isIgnoringMetadata()) {
                 // Compare the name because it was ignored by super.equals(…) in "ignore metadata" mode.
                 return Objects.equals(getName(), that.getName());
             }

Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -325,8 +325,9 @@ public final class ServiceParameter exte
                 that.getDefaultValue() == null &&
                 that.getValueClass()   == getValueClass())
             {
-                if (mode.ordinal() >= ComparisonMode.IGNORE_METADATA.ordinal()) {
+                if (mode.isIgnoringMetadata()) {
                     return Objects.equals(toString(getName()), toString(that.getName()));
+                    // super.equals(…) already compared 'getName()' in others mode.
                 }
                 return that.getMinimumOccurs() == getMinimumOccurs() &&
                        that.getMaximumOccurs() == getMaximumOccurs() &&

Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -36,7 +36,6 @@ import org.opengis.util.InternationalStr
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.StandardDateFormat;
 import org.apache.sis.measure.Units;
-import org.apache.sis.util.Workaround;
 import org.apache.sis.util.logging.Logging;
 
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -80,16 +79,6 @@ abstract class AbstractParser implements
     static final int MANDATORY = 2;
 
     /**
-     * Set to {@code true} if parsing of number in scientific notation is allowed.
-     * The way to achieve that is currently a hack, because {@link NumberFormat}
-     * has no API for managing that as of JDK 1.8.
-     *
-     * @todo See if a future version of JDK allows us to get ride of this ugly hack.
-     */
-    @Workaround(library = "JDK", version = "1.8")
-    static final boolean SCIENTIFIC_NOTATION = true;
-
-    /**
      * The logger to use for reporting warnings when this parser is used through the {@link #createFromWKT(String)}.
      * This happen most often when the user invoke the {@link org.apache.sis.referencing.CRS#fromWKT(String)}
      * convenience method.
@@ -175,7 +164,7 @@ abstract class AbstractParser implements
         this.dateFormat  = dateFormat;
         this.unitFormat  = unitFormat;
         this.errorLocale = errorLocale;
-        if (SCIENTIFIC_NOTATION && numberFormat instanceof DecimalFormat) {
+        if (Symbols.SCIENTIFIC_NOTATION && numberFormat instanceof DecimalFormat) {
             final DecimalFormat decimalFormat = (DecimalFormat) ((DecimalFormat) numberFormat).clone();
             exponentSymbol = decimalFormat.getDecimalFormatSymbols().getExponentSeparator();
             String pattern = decimalFormat.toPattern();

Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -1100,17 +1100,32 @@ public class Formatter implements Locali
     public void append(final double number) {
         appendSeparator();
         setColor(ElementKind.NUMBER);
+        final double abs = Math.abs(number);
         /*
-         * The 2 below is for using two less fraction digits than the expected number accuracy.
-         * The intend is to give to DecimalFormat a chance to hide rounding errors, keeping in
-         * mind that the number value is not necessarily the original one (we may have applied
-         * a unit conversion). In the case of WGS84 semi-major axis in metres, we still have a
-         * maximum of 8 fraction digits, which is more than enough.
+         * Use scientific notation if the number magnitude is too high or too low. The threshold values used here
+         * may be different than the threshold values used in the standard 'StringBuilder.append(double)' method.
+         * In particular, we use a higher threshold for large numbers because ellipsoid axis lengths are above the
+         * JDK threshold when the axis length is given in feet (about 2.1E+7) while we still want to format them
+         * as usual numbers.
+         *
+         * Note that we perform this special formatting only if the 'NumberFormat' is not localized
+         * (which is the usual case).
          */
-        numberFormat.setMaximumFractionDigits(DecimalFunctions.fractionDigitsForValue(number, 2));
-        numberFormat.setMinimumFractionDigits(1); // Must be after setMaximumFractionDigits(…).
-        numberFormat.setRoundingMode(RoundingMode.HALF_EVEN);
-        numberFormat.format(number, buffer, dummy);
+        if (Symbols.SCIENTIFIC_NOTATION && (abs < 1E-3 || abs >= 1E+9) && symbols.getLocale() == Locale.ROOT) {
+            buffer.append(number);
+        } else {
+            /*
+             * The 2 below is for using two less fraction digits than the expected number accuracy.
+             * The intend is to give to DecimalFormat a chance to hide rounding errors, keeping in
+             * mind that the number value is not necessarily the original one (we may have applied
+             * a unit conversion). In the case of WGS84 semi-major axis in metres, we still have a
+             * maximum of 8 fraction digits, which is more than enough.
+             */
+            numberFormat.setMaximumFractionDigits(DecimalFunctions.fractionDigitsForValue(number, 2));
+            numberFormat.setMinimumFractionDigits(1); // Must be after setMaximumFractionDigits(…).
+            numberFormat.setRoundingMode(RoundingMode.HALF_EVEN);
+            numberFormat.format(number, buffer, dummy);
+        }
         resetColor();
     }
 

Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -21,6 +21,7 @@ import java.util.Locale;
 import java.io.Serializable;
 import java.text.NumberFormat;
 import org.apache.sis.util.Localized;
+import org.apache.sis.util.Workaround;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.resources.Errors;
 
@@ -82,6 +83,16 @@ public class Symbols implements Localize
     private static final long serialVersionUID = -1730166945430878916L;
 
     /**
+     * Set to {@code true} if parsing and formatting of number in scientific notation is allowed.
+     * The way to achieve that is currently a hack, because {@link NumberFormat} has no API for
+     * managing that as of JDK 1.8.
+     *
+     * @todo See if a future version of JDK allows us to get ride of this ugly hack.
+     */
+    @Workaround(library = "JDK", version = "1.8")
+    static final boolean SCIENTIFIC_NOTATION = true;
+
+    /**
      * The prefix character for the value of a WKT fragment.
      */
     static final char FRAGMENT_VALUE = '$';

Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -29,6 +29,7 @@ import org.opengis.annotation.UML;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.ExtendedElementInformation;
 import org.apache.sis.internal.util.Citations;
+import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.measure.ValueRange;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.Classes;
@@ -48,7 +49,6 @@ import org.apache.sis.xml.IdentifiedObje
 
 import static org.apache.sis.metadata.PropertyComparator.*;
 import static org.apache.sis.metadata.ValueExistencePolicy.isNullOrEmpty;
-import static org.apache.sis.internal.util.Numerics.floatEpsilonEqual;
 import static org.apache.sis.internal.util.CollectionsExt.snapshot;
 import static org.apache.sis.internal.util.CollectionsExt.modifiableCopy;
 import static org.apache.sis.util.collection.Containers.hashMapCapacity;
@@ -176,9 +176,8 @@ class PropertyAccessor {
     private final Method[] setters;
 
     /**
-     * The JavaBeans property names. They are computed at construction time,
-     * {@linkplain String#intern() interned} then cached. Those names are often
-     * the same than field names (at least in SIS implementation), so it is
+     * The JavaBeans property names. They are computed at construction time, {@linkplain String#intern() interned}
+     * then cached. Those names are often the same than field names (at least in SIS implementation), so it is
      * reasonable to intern them in order to share {@code String} instances.
      *
      * <p>This array shall not contains any {@code null} elements.</p>
@@ -1112,10 +1111,17 @@ class PropertyAccessor {
                 // Empty strings are also considered equal to null (this is more questionable).
                 continue;
             }
-            if (!Utilities.deepEquals(value1, value2, mode)) {
-                if (mode.ordinal() >= ComparisonMode.APPROXIMATIVE.ordinal() && floatEpsilonEqual(value1, value2)) {
-                    continue; // Accept this slight difference.
-                }
+            final boolean equals;
+            if ((value1 instanceof Double || value1 instanceof Float) &&
+                (value2 instanceof Double || value2 instanceof Float))
+            {
+                equals = Numerics.epsilonEqual(((Number) value1).doubleValue(),
+                                               ((Number) value2).doubleValue(), mode);
+            } else {
+                equals = Utilities.deepEquals(value1, value2, mode);
+            }
+            if (!equals) {
+                assert (mode != ComparisonMode.DEBUG) : type.getSimpleName() + '.' + names[i] + " differ.";
                 return false;
             }
         }

Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -32,6 +32,7 @@ import org.apache.sis.metadata.MetadataS
 import org.apache.sis.metadata.ModifiableMetadata;
 import org.apache.sis.internal.jaxb.IdentifierMapWithSpecialCases;
 import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.internal.util.Utilities;
 import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.CharSequences;
@@ -107,7 +108,7 @@ public class ISOMetadata extends Modifia
                  * without invoking super.getIdentifiers(), in which case their identifiers will not be copied.
                  * For safety, we will do this optimization only if the implementation is an Apache SIS one.
                  */
-                if (object.getClass().getName().startsWith("org.apache.sis.")) {
+                if (Utilities.isSIS(object.getClass())) {
                     return;
                 }
             }

Modified: sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/test/MetadataAssert.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/test/MetadataAssert.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/test/MetadataAssert.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/test/MetadataAssert.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -30,7 +30,7 @@ import org.apache.sis.io.wkt.Convention;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.6
  * @module
  */
 public strictfp class MetadataAssert extends Assert {
@@ -109,4 +109,31 @@ public strictfp class MetadataAssert ext
                     ((IdentifiedObject) object).getName().getCode() : object.getClass().getSimpleName(), expected, wkt);
         }
     }
+
+    /**
+     * Asserts that the WKT of the given object according the given convention is equal to the given regular expression.
+     * This method is like {@link #assertWktEquals(String, Object)}, but the use of regular expression allows some
+     * tolerance for example on numerical parameter values that may be subject to a limited form of rounding errors.
+     *
+     * @param convention The WKT convention to use.
+     * @param expected   The expected regular expression, or {@code null} if {@code object} is expected to be null.
+     * @param object     The object to format in <cite>Well Known Text</cite> format, or {@code null}.
+     *
+     * @since 0.6
+     */
+    public static void assertWktEqualsRegex(final Convention convention, final String expected, final Object object) {
+        if (expected == null) {
+            assertNull(object);
+        } else {
+            assertNotNull(object);
+            final String wkt;
+            synchronized (WKT_FORMAT) {
+                WKT_FORMAT.setConvention(convention);
+                wkt = WKT_FORMAT.format(object);
+            }
+            if (!wkt.matches(expected)) {
+                fail("WKT does not match the expected regular expression. The WKT that we got is:\n" + wkt);
+            }
+        }
+    }
 }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -530,6 +530,7 @@ public abstract class AbstractEnvelope i
      *
      * @since 0.4
      */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public Envelope[] toSimpleEnvelopes() {
         long isWrapAround = 0; // A bitmask of the dimensions having a "wrap around" behavior.
         CoordinateReferenceSystem crs = null;

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -106,9 +106,7 @@ public final class Formulas extends Stat
 
     /**
      * Returns the radius of a hypothetical sphere having the same surface than the ellipsoid
-     * specified by the given axis length. This method does not verify if {@code a == b}
-     * (in which case {@code a} could be returned directly); it is up to the caller to perform
-     * such optimization if desired.
+     * specified by the given axis length.
      *
      * @param  a The semi-major axis length.
      * @param  b The semi-minor axis length.
@@ -125,4 +123,36 @@ public final class Formulas extends Stat
             return a;
         }
     }
+
+    /**
+     * Computes the semi-minor axis length from the given semi-major axis and inverse flattening factor.
+     *
+     * @param  semiMajorAxis     The semi-major axis length.
+     * @param  inverseFlattening The inverse flattening factor.
+     * @return The semi-minor axis length.
+     */
+    public static double getSemiMinor(final double semiMajorAxis, final double inverseFlattening) {
+        /*
+         * Note: double-double arithmetic does not increase the accuracy here, unless the inverse flattening
+         * factor given to this method is very high (i.e. the planet is very close to a perfect sphere).
+         */
+        return semiMajorAxis * (1 - 1/inverseFlattening);
+    }
+
+    /**
+     * Computes the inverse flattening factor from the given axis lengths.
+     *
+     * @param  semiMajorAxis The semi-major axis length.
+     * @param  semiMinorAxis The semi-minor axis length.
+     * @return The inverse flattening factor.
+     */
+    public static double getInverseFlattening(final double semiMajorAxis, final double semiMinorAxis) {
+        /*
+         * Note: double-double arithmetic here sometime change the last digit. We ignore for now.
+         * We may consider using double-double arithmetic in a future SIS version, not for more
+         * accurate map projection but rather for being able to find back the original value after
+         * we convert back and forward betwen inverse flattening and semi-minor axis length.
+         */
+        return semiMajorAxis / (semiMajorAxis - semiMinorAxis);
+    }
 }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -36,7 +36,6 @@ import org.apache.sis.referencing.crs.De
 import org.apache.sis.referencing.cs.AxesConvention;
 
 import static java.util.Collections.singletonMap;
-import static org.apache.sis.internal.util.Numerics.epsilonEqual;
 
 
 /**
@@ -59,27 +58,6 @@ public final class ReferencingUtilities
     }
 
     /**
-     * Returns {@code true} if the Greenwich longitude of the {@code actual} prime meridian is equals to the
-     * Greenwich longitude of the {@code expected} prime meridian. The comparison is performed in unit of the
-     * expected prime meridian.
-     *
-     * <p>A {@code null} argument is interpreted as "unknown prime meridian". Consequently this method
-     * unconditionally returns {@code false} if one or both arguments is {@code null}.</p>
-     *
-     * @param expected The expected prime meridian, or {@code null}.
-     * @param actual The actual prime meridian, or {@code null}.
-     * @return {@code true} if both prime meridian have the same Greenwich longitude,
-     *         in unit of the expected prime meridian.
-     */
-    public static boolean isGreenwichLongitudeEquals(final PrimeMeridian expected, final PrimeMeridian actual) {
-        if (expected == null || actual == null) {
-            return false; // See method javadoc.
-        }
-        return (expected == actual) || epsilonEqual(expected.getGreenwichLongitude(),
-                getGreenwichLongitude(actual, expected.getAngularUnit()));
-    }
-
-    /**
      * Returns the longitude value relative to the Greenwich Meridian, expressed in the specified units.
      * This method provides the same functionality than {@link DefaultPrimeMeridian#getGreenwichLongitude(Unit)},
      * but on arbitrary implementation.

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -20,7 +20,7 @@ import org.opengis.parameter.ParameterDe
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.ConicProjection;
 import org.apache.sis.parameter.Parameters;
-import org.apache.sis.referencing.operation.projection.LambertConformal;
+import org.apache.sis.referencing.operation.projection.LambertConicConformal;
 import org.apache.sis.referencing.operation.projection.NormalizedProjection;
 
 
@@ -74,6 +74,6 @@ class AbstractLambert extends MapProject
      */
     @Override
     protected final NormalizedProjection createProjection(final Parameters parameters) {
-        return new LambertConformal(this, parameters);
+        return new LambertConicConformal(this, parameters);
     }
 }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -126,7 +126,7 @@ public final class Equirectangular exten
                 .addName("Latitude of 1st standard parallel")
                 .addName(Citations.OGC,     Constants.STANDARD_PARALLEL_1)
                 .addName(Citations.ESRI,    "Standard_Parallel_1")
-                .addName(Citations.NETCDF,  "standard_parallel")
+                .addName(Citations.NETCDF,  Constants.STANDARD_PARALLEL)
                 .addName(Citations.GEOTIFF, "ProjStdParallel1")
                 .addName(Citations.PROJ4,   "lat_ts"), false);
 
@@ -144,7 +144,7 @@ public final class Equirectangular exten
                 .addName("False easting")
                 .addName(Citations.OGC,     Constants.FALSE_EASTING)
                 .addName(Citations.ESRI,    "False_Easting")
-                .addName(Citations.NETCDF,  "false_easting")
+                .addName(Citations.NETCDF,  Constants.FALSE_EASTING)
                 .addName(Citations.GEOTIFF, "FalseEasting")
                 .addName(Citations.PROJ4,   "x_0"));
 
@@ -153,7 +153,7 @@ public final class Equirectangular exten
                 .addName("False northing")
                 .addName(Citations.OGC,     Constants.FALSE_NORTHING)
                 .addName(Citations.ESRI,    "False_Northing")
-                .addName(Citations.NETCDF,  "false_northing")
+                .addName(Citations.NETCDF,  Constants.FALSE_NORTHING)
                 .addName(Citations.GEOTIFF, "FalseNorthing")
                 .addName(Citations.PROJ4,   "y_0"));
         /*

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -136,15 +136,15 @@ public abstract class MapProjection exte
      *
      * @see #createConstant(ParameterBuilder, Double)
      */
-    public static void validate(final ParameterDescriptor<Double> descriptor, final double value)
+    public static void validate(final ParameterDescriptor<? extends Number> descriptor, final double value)
             throws IllegalArgumentException
     {
         if (Double.isNaN(value) || Double.isInfinite(value)) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalParameterValue_2,
                     descriptor.getName(), value));
         }
-        final Comparable<Double> min = descriptor.getMinimumValue();
-        final Comparable<Double> max = descriptor.getMaximumValue();
+        final Comparable<? extends Number> min = descriptor.getMinimumValue();
+        final Comparable<? extends Number> max = descriptor.getMaximumValue();
         if (!Objects.equals(min, max)) {
             /*
              * RATIONAL: why we do not check the bounds if (min == max):

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -322,8 +322,9 @@ public class DefaultParameterDescriptor<
      *         or {@code null} if it does not apply or if there is no restriction.
      */
     @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public Set<T> getValidValues() {
-        return validValues;
+        return validValues;   // Null or unmodifiable
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -58,30 +58,6 @@ final class MapProjectionDescriptor exte
     private static final long serialVersionUID = -9142116135803309453L;
 
     /**
-     * The NetCDF parameter name for the Earth radius.
-     *
-     * @see Constants#SEMI_MAJOR
-     * @see Constants#SEMI_MINOR
-     */
-    static final String EARTH_RADIUS = "earth_radius";
-
-    /**
-     * The NetCDF parameter name for inverse flattening.
-     *
-     * @see Constants#SEMI_MAJOR
-     * @see Constants#SEMI_MINOR
-     */
-    static final String INVERSE_FLATTENING = "inverse_flattening";
-
-    /**
-     * The NetCDF parameter name for the standard parallels.
-     *
-     * @see Constants#STANDARD_PARALLEL_1
-     * @see Constants#STANDARD_PARALLEL_2
-     */
-    static final String STANDARD_PARALLEL = "standard_parallel";
-
-    /**
      * {@code true} if the {@link #STANDARD_PARALLEL} parameter can be added.
      */
     final boolean hasStandardParallels;
@@ -144,14 +120,17 @@ final class MapProjectionDescriptor exte
      */
     @Override
     public GeneralParameterDescriptor descriptor(final String name) throws ParameterNotFoundException {
-        if (isHeuristicMatchForName(name, EARTH_RADIUS)) {
+        if (isHeuristicMatchForName(name, Constants.EARTH_RADIUS)) {
             return MapProjectionParameters.EarthRadius.DESCRIPTOR;
         }
-        if (isHeuristicMatchForName(name, INVERSE_FLATTENING)) {
+        if (isHeuristicMatchForName(name, Constants.INVERSE_FLATTENING)) {
             return MapProjectionParameters.InverseFlattening.DESCRIPTOR;
         }
+        if (isHeuristicMatchForName(name, Constants.IS_IVF_DEFINITIVE)) {
+            return MapProjectionParameters.IsIvfDefinitive.DESCRIPTOR;
+        }
         if (hasStandardParallels) {
-            if (isHeuristicMatchForName(name, STANDARD_PARALLEL)) {
+            if (isHeuristicMatchForName(name, Constants.STANDARD_PARALLEL)) {
                 return MapProjectionParameters.StandardParallel.DESCRIPTOR;
             }
         }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -33,6 +33,9 @@ import org.apache.sis.util.ArraysExt;
 import static org.opengis.referencing.IdentifiedObject.NAME_KEY;
 import static org.apache.sis.metadata.iso.citation.Citations.NETCDF;
 
+// Branch-specific imports
+import org.apache.sis.internal.jdk7.Objects;
+
 
 /**
  * Map projection parameters, with special processing for alternative ways to express the ellipsoid axis length
@@ -60,7 +63,7 @@ final class MapProjectionParameters exte
      * The {@link InverseFlattening} parameter instance, created when first needed.
      * This is an "invisible" parameter, never shown in the {@link #values()} list.
      */
-    private transient ParameterValue<Double> inverseFlattening;
+    private transient InverseFlattening inverseFlattening;
 
     /**
      * The {@link StandardParallel} parameter instance, created when first needed.
@@ -69,6 +72,12 @@ final class MapProjectionParameters exte
     private transient ParameterValue<double[]> standardParallel;
 
     /**
+     * The {@link IsIvfDefinitive} parameter instance, created when first needed.
+     * This is an "invisible" parameter, never shown in the {@link #values()} list.
+     */
+    private transient ParameterValue<Boolean> isIvfDefinitive;
+
+    /**
      * Creates a new parameter value group. An instance of {@link MapProjectionDescriptor}
      * is mandatory, because some method in this class will need to cast the descriptor.
      */
@@ -97,38 +106,46 @@ final class MapProjectionParameters exte
      */
     @Override
     ParameterValue<?> parameterIfExist(final String name) throws ParameterNotFoundException {
-        if (MapProjectionDescriptor.isHeuristicMatchForName(name, MapProjectionDescriptor.EARTH_RADIUS)) {
-            ParameterValue<?> value = earthRadius;
-            if (value == null) {
-                value = earthRadius = new EarthRadius(
-                        parameter(Constants.SEMI_MAJOR),
-                        parameter(Constants.SEMI_MINOR));
+        if (MapProjectionDescriptor.isHeuristicMatchForName(name, Constants.EARTH_RADIUS)) {
+            if (earthRadius == null) {
+                earthRadius = new EarthRadius(parameter(Constants.SEMI_MAJOR),
+                                              parameter(Constants.SEMI_MINOR));
             }
-            return value;
+            return earthRadius;
+        }
+        if (MapProjectionDescriptor.isHeuristicMatchForName(name, Constants.INVERSE_FLATTENING)) {
+            return getInverseFlattening();
         }
-        if (MapProjectionDescriptor.isHeuristicMatchForName(name, MapProjectionDescriptor.INVERSE_FLATTENING)) {
-            ParameterValue<?> value = inverseFlattening;
-            if (value == null) {
-                value = inverseFlattening = new InverseFlattening(
-                        parameter(Constants.SEMI_MAJOR),
-                        parameter(Constants.SEMI_MINOR));
+        if (MapProjectionDescriptor.isHeuristicMatchForName(name, Constants.IS_IVF_DEFINITIVE)) {
+            if (isIvfDefinitive == null) {
+                isIvfDefinitive = new IsIvfDefinitive(getInverseFlattening());
             }
-            return value;
+            return isIvfDefinitive;
         }
         if (((MapProjectionDescriptor) getDescriptor()).hasStandardParallels) {
-            if (MapProjectionDescriptor.isHeuristicMatchForName(name, MapProjectionDescriptor.STANDARD_PARALLEL)) {
-                ParameterValue<?> value = standardParallel;
-                if (value == null) {
-                    value = standardParallel = new StandardParallel(
-                            parameter(Constants.STANDARD_PARALLEL_1),
-                            parameter(Constants.STANDARD_PARALLEL_2));
+            if (MapProjectionDescriptor.isHeuristicMatchForName(name, Constants.STANDARD_PARALLEL)) {
+                if (standardParallel == null) {
+                    standardParallel = new StandardParallel(parameter(Constants.STANDARD_PARALLEL_1),
+                                                            parameter(Constants.STANDARD_PARALLEL_2));
                 }
-                return value;
+                return standardParallel;
             }
         }
         return super.parameterIfExist(name);
     }
 
+    /**
+     * Returns the {@link InverseFlattening} instance, creating it when first needed.
+     * This parameter is used also by {@link IsIvfDefinitive}.
+     */
+    private InverseFlattening getInverseFlattening() {
+        if (inverseFlattening == null) {
+            inverseFlattening = new InverseFlattening(parameter(Constants.SEMI_MAJOR),
+                                                      parameter(Constants.SEMI_MINOR));
+        }
+        return inverseFlattening;
+    }
+
 
 
 
@@ -152,17 +169,10 @@ final class MapProjectionParameters exte
          * This is not a standard parameter.
          */
         static final ParameterDescriptor<Double> DESCRIPTOR = new DefaultParameterDescriptor<Double>(
-                toMap(MapProjectionDescriptor.EARTH_RADIUS), 0, 1, Double.class,
+                InverseFlattening.toMap(Constants.EARTH_RADIUS), 0, 1, Double.class,
                 MeasurementRange.createGreaterThan(0.0, SI.METRE), null, null);
 
         /**
-         * Helper method for {@link #DESCRIPTOR} constructions.
-         */
-        static Map<String,?> toMap(final String name) {
-            return Collections.singletonMap(NAME_KEY, new NamedIdentifier(NETCDF, name));
-        }
-
-        /**
          * The parameters for the semi-major and semi-minor axis length.
          */
         private final ParameterValue<?> semiMajor, semiMinor;
@@ -181,8 +191,8 @@ final class MapProjectionParameters exte
          */
         @Override
         protected void setValue(final Object value, final Unit<?> unit) {
-            super.setValue(value, unit);   // Perform argument check.
-            final double r = (Double) value;
+            super.setValue(value, unit);        // Perform argument check.
+            final double r = (Double) value;    // At this point, can not be anything else than Double.
             semiMajor.setValue(r, unit);
             semiMinor.setValue(r, unit);
         }
@@ -243,21 +253,60 @@ final class MapProjectionParameters exte
          * This is not a standard parameter.
          */
         static final ParameterDescriptor<Double> DESCRIPTOR = new DefaultParameterDescriptor<Double>(
-                EarthRadius.toMap(MapProjectionDescriptor.INVERSE_FLATTENING), 0, 1, Double.class,
+                toMap(Constants.INVERSE_FLATTENING), 0, 1, Double.class,
                 MeasurementRange.createGreaterThan(0.0, Unit.ONE), null, null);
 
         /**
+         * Helper method for {@link #DESCRIPTOR} constructions.
+         */
+        static Map<String,?> toMap(final String name) {
+            return Collections.singletonMap(NAME_KEY, new NamedIdentifier(NETCDF, name));
+        }
+
+        /**
          * The parameters for the semi-major and semi-minor axis length.
          */
         private final ParameterValue<?> semiMajor, semiMinor;
 
         /**
+         * The declared inverse flattening values, together with a snapshot of axis lengths
+         * at the time the inverse flattening has been set.
+         */
+        private double inverseFlattening, a, b;
+
+        /**
          * Creates a new parameter.
          */
         InverseFlattening(final ParameterValue<?> semiMajor, final ParameterValue<?> semiMinor) {
             super(DESCRIPTOR);
             this.semiMajor = semiMajor;
             this.semiMinor = semiMinor;
+            invalidate();
+        }
+
+        /**
+         * Declares that the inverse flattening factor is not definitive.
+         * We use the fact that the {@code ==} operator gives {@code false} if a value is NaN.
+         */
+        void invalidate() {
+            a = b = Double.NaN;
+        }
+
+        /**
+         * Returns {@code true} if the inverse flattening factor has been explicitely specified
+         * and seems to still valid.
+         */
+        boolean isIvfDefinitive() {
+            if (inverseFlattening > 0) {
+                final Number ca = (Number) semiMajor.getValue();
+                if (ca != null && ca.doubleValue() == a) {
+                    final Number cb = (Number) semiMinor.getValue();
+                    if (cb != null && cb.doubleValue() == b) {
+                        return Objects.equals(semiMajor.getUnit(), semiMinor.getUnit());
+                    }
+                }
+            }
+            return false;
         }
 
         /**
@@ -266,28 +315,31 @@ final class MapProjectionParameters exte
          */
         @Override
         protected void setValue(final Object value, final Unit<?> unit) {
-            super.setValue(value, unit);   // Perform argument check.
-            final double ivf = (Double) value;
-            if (!Double.isNaN(ivf)) {
-                final Double a = (Double) semiMajor.getValue();
-                if (a != null) {
-                    semiMinor.setValue(a * (1 - 1/ivf), semiMajor.getUnit());
-                }
+            super.setValue(value, unit);        // Perform argument check.
+            final double ivf = (Double) value;  // At this point, can not be anything else than Double.
+            final Number ca = (Number) semiMajor.getValue();
+            if (ca != null) {
+                a = ca.doubleValue();
+                b = Formulas.getSemiMinor(a, ivf);
+                semiMinor.setValue(b, semiMajor.getUnit());
+            } else {
+                invalidate();
             }
+            inverseFlattening = ivf;
         }
 
         /**
-         * Invoked when the parameter value is requested.
-         * Unconditionally computes the inverse flattening factor from the axis lengths.
+         * Invoked when the parameter value is requested. Computes the inverse flattening factor
+         * from the axis lengths if the currently stored value does not seem to be valid anymore.
          */
         @Override
         public double doubleValue() {
-            final Double a = (Double) semiMajor.getValue();
-            if (a != null && semiMinor.getValue() != null) {
-                final double b = semiMinor.doubleValue(semiMajor.getUnit());
-                return a / (a - b);
+            final double ca = semiMajor.doubleValue();
+            final double cb = semiMinor.doubleValue(semiMajor.getUnit());
+            if (ca == a && cb == b && inverseFlattening > 0) {
+                return inverseFlattening;
             }
-            return Double.NaN;
+            return Formulas.getInverseFlattening(ca, cb);
         }
 
         /**
@@ -303,6 +355,69 @@ final class MapProjectionParameters exte
 
 
     /**
+     * Whether the inverse flattening parameter is definitive.
+     *
+     * @see org.apache.sis.referencing.datum.DefaultEllipsoid#isIvfDefinitive()
+     */
+    static final class IsIvfDefinitive extends DefaultParameterValue<Boolean> {
+        /**
+         * For cross-version compatibility. Actually instances of this class
+         * are not expected to be serialized, but we try to be a bit safer here.
+         */
+        private static final long serialVersionUID = 5988883252321358629L;
+
+        /**
+         * All names known to Apache SIS for the "is IVF definitive" parameter.
+         * This is not a standard parameter.
+         */
+        static final ParameterDescriptor<Boolean> DESCRIPTOR = new DefaultParameterDescriptor<Boolean>(
+                InverseFlattening.toMap(Constants.IS_IVF_DEFINITIVE), 0, 1, Boolean.class, null, null, null);
+
+        /**
+         * The parameters for the inverse flattening factor.
+         */
+        private final InverseFlattening inverseFlattening;
+
+        /**
+         * Creates a new parameter.
+         */
+        IsIvfDefinitive(final InverseFlattening inverseFlattening) {
+            super(DESCRIPTOR);
+            this.inverseFlattening = inverseFlattening;
+        }
+
+        /**
+         * Invoked when a new parameter value is set.
+         */
+        @Override
+        protected void setValue(final Object value, final Unit<?> unit) {
+            super.setValue(value, unit);   // Perform argument check.
+            if (!(Boolean) value) {
+                inverseFlattening.invalidate();
+            }
+        }
+
+        /**
+         * Invoked when the parameter value is requested.
+         */
+        @Override
+        public boolean booleanValue() {
+            return inverseFlattening.isIvfDefinitive();
+        }
+
+        /**
+         * Getters other than the above {@code booleanValue()} delegate to this method.
+         */
+        @Override
+        public Boolean getValue() {
+            return booleanValue();
+        }
+    }
+
+
+
+
+    /**
      * The standard parallels parameter as an array of {@code double}. This parameter is computed automatically
      * from the {@code "standard_parallel_1"} and {@code "standard_parallel_1"} standard parameters. When this
      * non-standard parameter is explicitely set, the array elements are given to the above-cited standard parameters.
@@ -320,7 +435,7 @@ final class MapProjectionParameters exte
          * {@link #STANDARD_PARALLEL_2}. This is not a standard parameter.
          */
         static final ParameterDescriptor<double[]> DESCRIPTOR = new DefaultParameterDescriptor<double[]>(
-                EarthRadius.toMap(MapProjectionDescriptor.STANDARD_PARALLEL),
+                InverseFlattening.toMap(Constants.STANDARD_PARALLEL),
                 0, 1, double[].class, null, null, null);
 
         /**
@@ -369,15 +484,15 @@ final class MapProjectionParameters exte
          */
         @Override
         public double[] getValue() {
-            final Double p1 = (Double) standardParallel1.getValue();
-            final Double p2 = (Double) standardParallel2.getValue();
+            final Number p1 = (Number) standardParallel1.getValue();
+            final Number p2 = (Number) standardParallel2.getValue();
             if (p2 == null) {
                 if (p1 == null) {
                     return ArraysExt.EMPTY_DOUBLE;
                 }
-                return new double[] {p1};
+                return new double[] {p1.doubleValue()};
             }
-            return new double[] {(p1 != null) ? p1 : Double.NaN, p2};
+            return new double[] {(p1 != null) ? p1.doubleValue() : Double.NaN, p2.doubleValue()};
         }
     }
 }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -126,6 +126,20 @@ public class ParameterBuilder extends Bu
     }
 
     /**
+     * Creates a new builder initialized to properties of the given object.
+     *
+     * @param descriptor The descriptor from which to inherit properties, or {@code null}.
+     *
+     * @since 0.6
+     */
+    public ParameterBuilder(final GeneralParameterDescriptor descriptor) {
+        super(descriptor);
+        if (descriptor != null) {
+            required = descriptor.getMinimumOccurs() != 0;
+        }
+    }
+
+    /**
      * Sets whether the parameter is mandatory or optional.
      * This property determines the {@linkplain DefaultParameterDescriptor#getMinimumOccurs() minimum number
      * of times} that values are required, which will be 0 for an optional parameter and 1 for a mandatory one.
@@ -148,7 +162,7 @@ public class ParameterBuilder extends Bu
      * Boxes the given value if non-NaN, or returns {@code null} if the value is {@code NaN}.
      */
     private static Double valueOf(final double value) {
-        return Double.isNaN(value) ? null : Double.valueOf(value);
+        return Double.isNaN(value) ? null : value;
     }
 
     /**
@@ -371,7 +385,7 @@ public class ParameterBuilder extends Bu
      *   <tr><td>{@code "semi_major"}</td>         <td>Always</td>     <td>Standard parameter defined by WKT 1.</td></tr>
      *   <tr><td>{@code "semi_minor"}</td>         <td>Always</td>     <td>Standard parameter defined by WKT 1.</td></tr>
      *   <tr><td>{@code "earth_radius"}</td>       <td>Hidden</td>     <td>Mapped to {@code "semi_major"} and {@code "semi_minor"} parameters.</td></tr>
-     *   <tr><td>{@code "inverse_flattening"}</td> <td>Hidden</td>     <td>Mapped to {@code "semi_major"} and {@code "semi_minor"} parameters.</td></tr>
+     *   <tr><td>{@code "inverse_flattening"}</td> <td>Hidden</td>     <td>Computed from the {@code "semi_major"} and {@code "semi_minor"} parameters.</td></tr>
      *   <tr><td>{@code "standard_parallel"}</td>  <td>Hidden</td>
      *     <td>Array of 1 or 2 elements mapped to {@code "standard_parallel_1"} and {@code "standard_parallel_2"}.</td></tr>
      * </table>

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.List;
 import java.util.HashMap;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.lang.reflect.Type;
 import java.lang.reflect.ParameterizedType;
 import org.opengis.util.NameSpace;
@@ -204,10 +205,9 @@ public abstract class Builder<B extends
 
     /**
      * The codespace as a {@code NameSpace} object, or {@code null} if not yet created.
-     *
-     * @see #namespace()
+     * This object is built from the {@value org.opengis.metadata.Identifier#CODESPACE_KEY} value when first needed.
      */
-    private NameSpace namespace;
+    private transient NameSpace namespace;
 
     /**
      * The name factory, fetched when first needed.
@@ -257,6 +257,26 @@ public abstract class Builder<B extends
     }
 
     /**
+     * Creates a new builder initialized to properties of the given object.
+     * The properties recognized by this constructor are documented in the
+     * {@link IdentifiedObjects#getProperties(IdentifiedObject, String...)} method.
+     *
+     * @param object The identified object from which to inherit properties, or {@code null}.
+     *
+     * @since 0.6
+     */
+    protected Builder(final IdentifiedObject object) {
+        this();
+        if (object != null) {
+            properties.putAll(IdentifiedObjects.getProperties(object));
+            final GenericName[] valueAlias = (GenericName[]) properties.remove(IdentifiedObject.ALIAS_KEY);
+            final ReferenceIdentifier[] valueIds = (ReferenceIdentifier[])  properties.remove(IdentifiedObject.IDENTIFIERS_KEY);
+            if (valueAlias != null) aliases.addAll(Arrays.asList(valueAlias));
+            if (valueIds != null) identifiers.addAll(Arrays.asList(valueIds));
+        }
+    }
+
+    /**
      * Returns the name factory to use for creating namespaces and local names.
      * The factory will be fetched when first needed, and while not change anymore
      * for the rest of this {@code Builder} lifetime.
@@ -434,31 +454,6 @@ public abstract class Builder<B extends
     }
 
     /**
-     * Sets whether the next {@code IdentifiedObject}s to create shall be considered deprecated. Deprecated objects
-     * exist in some {@linkplain org.opengis.referencing.AuthorityFactory authority factories} like the EPSG database.
-     *
-     * <p>Note that this method does not apply to name and identifiers, which have their own
-     * {@code addDeprecatedFoo(…)} methods.</p>
-     *
-     * <p><b>Lifetime:</b>
-     * this property is kept unchanged until this {@code setDeprecated(…)} method is invoked again.</p>
-     *
-     * @param  deprecated {@code true} if the next names, identifiers and identified objects should be
-     *         considered deprecated, or {@code false} otherwise.
-     * @return {@code this}, for method call chaining.
-     *
-     * @see #addDeprecatedName(CharSequence, CharSequence)
-     * @see #addDeprecatedIdentifier(String, String)
-     * @see AbstractIdentifiedObject#isDeprecated()
-     *
-     * @since 0.6
-     */
-    public B setDeprecated(final boolean deprecated) {
-        properties.put(AbstractIdentifiedObject.DEPRECATED_KEY, deprecated);
-        return self();
-    }
-
-    /**
      * Adds an {@code IdentifiedObject} name given by a {@code String} or {@code InternationalString}.
      * The given string will be combined with the authority, {@link #setCodeSpace(Citation, String) code space}
      * and {@link #setVersion(String) version} information for creating the {@link Identifier} or {@link GenericName}
@@ -841,6 +836,31 @@ public abstract class Builder<B extends
         return self();
     }
 
+    /**
+     * Sets whether the next {@code IdentifiedObject}s to create shall be considered deprecated. Deprecated objects
+     * exist in some {@linkplain org.opengis.referencing.AuthorityFactory authority factories} like the EPSG database.
+     *
+     * <p>Note that this method does not apply to name and identifiers, which have their own
+     * {@code addDeprecatedFoo(…)} methods.</p>
+     *
+     * <p><b>Lifetime:</b>
+     * this property is kept unchanged until this {@code setDeprecated(…)} method is invoked again.</p>
+     *
+     * @param  deprecated {@code true} if the next names, identifiers and identified objects should be
+     *         considered deprecated, or {@code false} otherwise.
+     * @return {@code this}, for method call chaining.
+     *
+     * @see #addDeprecatedName(CharSequence, CharSequence)
+     * @see #addDeprecatedIdentifier(String, String)
+     * @see AbstractIdentifiedObject#isDeprecated()
+     *
+     * @since 0.6
+     */
+    public B setDeprecated(final boolean deprecated) {
+        properties.put(AbstractIdentifiedObject.DEPRECATED_KEY, deprecated);
+        return self();
+    }
+
     /**
      * Initializes/cleanups the {@link #properties} map before/after a {@code createXXX(…)} execution.
      * Subclasses shall invoke this method in their {@code createXXX(…)} methods as below:

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -28,6 +28,7 @@ import org.opengis.util.ScopedName;
 import org.opengis.util.GenericName;
 import org.opengis.util.NameFactory;
 import org.opengis.util.InternationalString;
+import org.apache.sis.util.resources.Errors;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.Identifier;
 import org.opengis.referencing.ReferenceIdentifier;
@@ -213,11 +214,20 @@ public class NamedIdentifier extends Imm
      */
     private static String toString(final CharSequence code) {
         ArgumentChecks.ensureNonNull("code", code);
+        final String c;
         if (code instanceof InternationalString) {
-            return ((InternationalString) code).toString(Locale.ROOT);
+            c = ((InternationalString) code).toString(Locale.ROOT);
         } else {
-            return code.toString();
+            c = code.toString();
         }
+        if (c != null) {
+            return c;
+        }
+        /*
+         * May happen if the user gave us an instance of 'org.apache.sis.internal.jaxb.gmx.Anchor' class
+         * (maybe he got the instance indirectly) and the construction of that instance is not completed.
+         */
+        throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentClass_2, "code", code.getClass()));
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -118,10 +118,10 @@ final class Properties extends AbstractM
     final Object getAt(final int key) {
         if ((excludeMask & (1 << key)) == 0) {
             switch (key) {
-                case 0: {
+                case 0: {   // NAME_KEY
                     return object.getName();
                 }
-                case 1: {
+                case 1: {   // IDENTIFIERS_KEY
                     final Collection<ReferenceIdentifier> c = object.getIdentifiers();
                     if (c != null) {
                         final int size = c.size();
@@ -131,7 +131,7 @@ final class Properties extends AbstractM
                     }
                     break;
                 }
-                case 2: {
+                case 2: {   // ALIAS_KEY
                     final Collection<GenericName> c = object.getAlias();
                     if (c != null) {
                         final int size = c.size();
@@ -141,10 +141,10 @@ final class Properties extends AbstractM
                     }
                     break;
                 }
-                case 3: {
+                case 3: {   // REMARKS_KEY
                     return object.getRemarks();
                 }
-                case 4: {
+                case 4: {   // SCOPE_KEY
                     if (object instanceof ReferenceSystem) {
                         return ((ReferenceSystem) object).getScope();
                     } else if (object instanceof Datum) {
@@ -154,7 +154,7 @@ final class Properties extends AbstractM
                     }
                     break;
                 }
-                case 5: {
+                case 5: {   // DOMAIN_OF_VALIDITY_KEY
                     if (object instanceof ReferenceSystem) {
                         return ((ReferenceSystem) object).getDomainOfValidity();
                     } else if (object instanceof Datum) {
@@ -164,13 +164,13 @@ final class Properties extends AbstractM
                     }
                     break;
                 }
-                case 6: {
+                case 6: {   // OPERATION_VERSION_KEY
                     if (object instanceof CoordinateOperation) {
                         return ((CoordinateOperation) object).getOperationVersion();
                     }
                     break;
                 }
-                case 7: {
+                case 7: {   // COORDINATE_OPERATION_ACCURACY_KEY
                     if (object instanceof CoordinateOperation) {
                         final Collection<PositionalAccuracy> c = ((CoordinateOperation) object).getCoordinateOperationAccuracy();
                         if (c != null) {

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -20,7 +20,7 @@ import java.util.Map;
 import javax.measure.unit.SI;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Length;
-import javax.measure.converter.ConversionException;
+import javax.measure.converter.UnitConverter;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -44,7 +44,6 @@ import org.apache.sis.util.resources.Err
 
 import static java.lang.Math.*;
 import static java.lang.Double.*;
-import static org.apache.sis.internal.util.Numerics.epsilonEqual;
 import static org.apache.sis.util.ArgumentChecks.ensureStrictlyPositive;
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
 
@@ -297,7 +296,7 @@ public class DefaultEllipsoid extends Ab
             return new Sphere(properties, semiMajorAxis, false, unit);
         } else {
             return new DefaultEllipsoid(properties, semiMajorAxis, semiMinorAxis,
-                       semiMajorAxis / (semiMajorAxis - semiMinorAxis), false, unit);
+                       Formulas.getInverseFlattening(semiMajorAxis, semiMinorAxis), false, unit);
         }
     }
 
@@ -321,7 +320,8 @@ public class DefaultEllipsoid extends Ab
             return new Sphere(properties, semiMajorAxis, true, unit);
         } else {
             return new DefaultEllipsoid(properties, semiMajorAxis,
-                    semiMajorAxis * (1 - 1/inverseFlattening), inverseFlattening, true, unit);
+                    Formulas.getSemiMinor(semiMajorAxis, inverseFlattening),
+                    inverseFlattening, true, unit);
         }
     }
 
@@ -359,11 +359,11 @@ public class DefaultEllipsoid extends Ab
     private void afterUnmarshal() {
         if (ivfDefinitive) {
             if (semiMinorAxis == 0) {
-                semiMinorAxis = semiMajorAxis * (1 - 1/inverseFlattening);
+                semiMinorAxis = Formulas.getSemiMinor(semiMajorAxis, inverseFlattening);
             }
         } else {
             if (inverseFlattening == 0) {
-                inverseFlattening = semiMajorAxis / (semiMajorAxis - semiMinorAxis);
+                inverseFlattening = Formulas.getInverseFlattening(semiMajorAxis, semiMinorAxis);
             }
         }
         if (unit == null) {
@@ -422,13 +422,10 @@ public class DefaultEllipsoid extends Ab
      * Sets the semi-major axis value.
      * This method is invoked by JAXB at unmarshalling time only.
      *
-     * @throws ConversionException If semi-major and semi-minor axes use inconsistent units
-     *         and we can not convert from one to the other.
-     *
      * @see #setSecondDefiningParameter(SecondDefiningParameter)
      * @see #afterUnmarshal()
      */
-    private void setSemiMajorAxisMeasure(final Measure measure) throws ConversionException {
+    private void setSemiMajorAxisMeasure(final Measure measure) {
         if (semiMajorAxis != 0) {
             warnDuplicated("semiMajorAxis");
         } else {
@@ -525,13 +522,10 @@ public class DefaultEllipsoid extends Ab
      * value or the semi minor axis value, according to what have been defined in the
      * second defining parameter given. This is for JAXB unmarshalling process only.
      *
-     * @throws ConversionException If semi-major and semi-minor axes use inconsistent units
-     *         and we can not convert from one to the other.
-     *
      * @see #setSemiMajorAxisMeasure(Measure)
      * @see #afterUnmarshal()
      */
-    private void setSecondDefiningParameter(SecondDefiningParameter second) throws ConversionException {
+    private void setSecondDefiningParameter(SecondDefiningParameter second) {
         while (second.secondDefiningParameter != null) {
             second = second.secondDefiningParameter;
         }
@@ -563,15 +557,13 @@ public class DefaultEllipsoid extends Ab
      * Ensures that the semi-minor axis uses the same unit than the semi-major one.
      * The {@link #unit} field shall be set to the semi-major axis unit before this method call.
      *
-     * @param  uom The semi-minor axis unit.
-     * @throws ConversionException If semi-major and semi-minor axes use inconsistent units
-     *         and we can not convert from one to the other.
+     * @param uom The semi-minor axis unit.
      */
-    private void harmonizeAxisUnits(final Unit<Length> uom) throws ConversionException {
+    private void harmonizeAxisUnits(final Unit<Length> uom) {
         if (unit == null) {
             unit = uom;
         } else if (uom != null && uom != unit) {
-            semiMinorAxis = uom.getConverterToAny(unit).convert(semiMinorAxis);
+            semiMinorAxis = uom.getConverterTo(unit).convert(semiMinorAxis);
         }
     }
 
@@ -730,12 +722,48 @@ public class DefaultEllipsoid extends Ab
                 }
                 // Fall through
             }
+            case IGNORE_METADATA: {
+                /*
+                 * "Inverse flattening factor" and "semi-minor axis length" are computed from each other,
+                 * so we do not need to compare both of them. But in non-approximative mode we nevertheless
+                 * compare both as a safety against rounding errors.
+                 */
+                if (!Numerics.equals(getInverseFlattening(), ((Ellipsoid) object).getInverseFlattening())) {
+                    return false;
+                }
+                // Fall through
+            }
             default: {
+                /*
+                 * Note: DefaultPrimeMeridian.equals(object, IGNORE_METADATA) ignores the unit.
+                 * But we do not perform the same relaxation here because the ellipsoid unit will
+                 * become the linear unit of map projections if the user does not overwrite them
+                 * with an explicit CoordinateSystem declaration.
+                 */
                 final Ellipsoid that = (Ellipsoid) object;
-                return epsilonEqual(getSemiMajorAxis(),     that.getSemiMajorAxis(),     mode) &&
-                       epsilonEqual(getSemiMinorAxis(),     that.getSemiMinorAxis(),     mode) &&
-                       epsilonEqual(getInverseFlattening(), that.getInverseFlattening(), mode) &&
-                       Objects.equals(getAxisUnit(),        that.getAxisUnit());
+                final Unit<Length> unit = getAxisUnit();  // In case the user override this method.
+                if (!Objects.equals(unit, that.getAxisUnit())) {
+                    return false;
+                }
+                final UnitConverter c = mode.isApproximative() ? unit.getConverterTo(SI.METRE) : null;
+                boolean isMinor = false;
+                double v1 = this.getSemiMajorAxis();
+                double v2 = that.getSemiMajorAxis();
+                if (c == null ? Numerics.equals(v1, v2) : Numerics.epsilonEqual(
+                        c.convert(v1), c.convert(v2), Formulas.LINEAR_TOLERANCE))
+                {
+                    isMinor = true;
+                    v1 = this.getSemiMinorAxis();
+                    v2 = that.getSemiMinorAxis();
+                    if (c == null ? Numerics.equals(v1, v2) : Numerics.epsilonEqual(
+                            c.convert(v1), c.convert(v2), Formulas.LINEAR_TOLERANCE))
+                    {
+                        return true;
+                    }
+                }
+                assert (mode != ComparisonMode.DEBUG) : Numerics.messageForDifference(
+                        isMinor ? "semiMinorAxis" : "semiMajorAxis", v1, v2);
+                return false;
             }
         }
     }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -29,6 +29,7 @@ import org.opengis.referencing.Reference
 import org.opengis.referencing.datum.PrimeMeridian;
 import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.apache.sis.referencing.AbstractIdentifiedObject;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.util.PatchedUnitFormat;
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.internal.jaxb.gco.Measure;
@@ -39,10 +40,10 @@ import org.apache.sis.util.ComparisonMod
 
 import static org.apache.sis.util.ArgumentChecks.ensureFinite;
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
-import static org.apache.sis.internal.referencing.ReferencingUtilities.canSetProperty;
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk7.Objects;
+import org.apache.sis.internal.referencing.Formulas;
 
 
 /**
@@ -265,7 +266,7 @@ public class DefaultPrimeMeridian extend
      * Invoked by JAXB for setting the Greenwich longitude and its unit of measurement.
      */
     private void setGreenwichMeasure(final Measure measure) {
-        if (measure != null && canSetProperty(DefaultPrimeMeridian.class,
+        if (measure != null && ReferencingUtilities.canSetProperty(DefaultPrimeMeridian.class,
                 "setGreenwichMeasure", "greenwichLongitude", greenwichLongitude != 0 || angularUnit != null))
         {
             greenwichLongitude = measure.value;
@@ -299,10 +300,7 @@ public class DefaultPrimeMeridian extend
         if (object == this) {
             return true; // Slight optimization.
         }
-        if (!super.equals(object, mode)) {
-            return false;
-        }
-        switch (mode) {
+        if (super.equals(object, mode)) switch (mode) {
             case STRICT: {
                 final DefaultPrimeMeridian that = (DefaultPrimeMeridian) object;
                 return Numerics.equals(this.greenwichLongitude, that.greenwichLongitude) &&
@@ -314,16 +312,25 @@ public class DefaultPrimeMeridian extend
                         Objects.equals(getAngularUnit(),        that.getAngularUnit());
             }
             default: {
-                final DefaultPrimeMeridian that = castOrCopy((PrimeMeridian) object);
-                return Numerics.epsilonEqual(this.getGreenwichLongitude(NonSI.DEGREE_ANGLE),
-                                             that.getGreenwichLongitude(NonSI.DEGREE_ANGLE), mode);
-                /*
-                 * Note: if mode==IGNORE_METADATA, we relax the unit check because EPSG uses
-                 *       sexagesimal degrees for the Greenwich meridian. Requirying the same
-                 *       unit prevent Geodetic.isWGS84(...) method to recognize EPSG's WGS84.
-                 */
+                final double v1 = getGreenwichLongitude(NonSI.DEGREE_ANGLE);
+                final double v2 = ReferencingUtilities.getGreenwichLongitude((PrimeMeridian) object, NonSI.DEGREE_ANGLE);
+                if (mode == ComparisonMode.IGNORE_METADATA) {
+                    /*
+                     * We relax the check on unit of measurement because EPSG uses sexagesimal degrees
+                     * for the Greenwich meridian.  Requirying the same unit would make more difficult
+                     * for isWGS84(…) methods to recognize EPSG's WGS84. We allow this relaxation here
+                     * because the unit of the prime meridian is usually not inherited by axes (indeed,
+                     * they are often not the same in the EPSG dataset). The same is not true for other
+                     * objects like DefaultEllipsoid.
+                     */
+                    return Numerics.equals(v1, v2);
+                } else if (Numerics.epsilonEqual(v1, v2, Formulas.ANGULAR_TOLERANCE)) {
+                    return true;
+                }
+                assert (mode != ComparisonMode.DEBUG) : Numerics.messageForDifference("greenwichLongitude", v1, v2);
             }
         }
+        return false;
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -23,6 +23,7 @@ import org.apache.sis.internal.util.Nume
 import org.apache.sis.internal.util.DoubleDouble;
 
 import static org.apache.sis.util.ArgumentChecks.*;
+import static org.apache.sis.internal.util.DoubleDouble.verbatim;
 import static org.apache.sis.internal.referencing.Formulas.JULIAN_YEAR_LENGTH;
 
 
@@ -159,7 +160,7 @@ public class TimeDependentBWP extends Bu
         if (time != null) {
             final long millis = time.getTime() - timeReference;
             if (millis != 0) { // Returns null for 0 as an optimization.
-                final DoubleDouble period = new DoubleDouble(millis, 0);
+                final DoubleDouble period = verbatim(millis);
                 period.divide(1000 * JULIAN_YEAR_LENGTH, 0);
                 return period;
             }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -32,6 +32,7 @@ import org.apache.sis.internal.referenci
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.internal.util.Utilities;
 import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.util.collection.WeakHashSet;
 import org.apache.sis.util.collection.Containers;
@@ -567,7 +568,7 @@ public class DefaultCoordinateOperationF
             return delegate;
         }
         for (final CoordinateOperationFactory factory : java.util.ServiceLoader.load(CoordinateOperationFactory.class)) {
-            if (!factory.getClass().getName().startsWith("org.apache.sis.")) {
+            if (!Utilities.isSIS(factory.getClass())) {
                 delegate = factory;
                 return factory;
             }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -305,7 +305,7 @@ public abstract class MatrixSIS implemen
             sum.clear();
             for (int j=0; j<numRow; j++) {
                 get(j, i, dot);
-                dot.multiply(dot);
+                dot.square();
                 sum.add(dot);
             }
             sum.sqrt();

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConformalProjection.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConformalProjection.java?rev=1693912&r1=1693911&r2=1693912&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConformalProjection.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConformalProjection.java [UTF-8] Mon Aug  3 14:46:30 2015
@@ -16,19 +16,15 @@
  */
 package org.apache.sis.referencing.operation.projection;
 
-import java.util.Map;
 import java.io.IOException;
 import java.io.ObjectInputStream;
-import org.opengis.parameter.ParameterDescriptor;
-import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.parameter.Parameters;
 
 import static java.lang.Math.*;
 
 
 /**
- * Base class of {@link LambertConformal}, {@link Mercator} and {@link PolarStereographic} projections.
+ * Base class of {@link LambertConicConformal}, {@link Mercator} and {@link PolarStereographic} projections.
  * All those projections have in common the property of being <cite>conformal</cite>, i.e. they preserve
  * angles locally. However we do not put this base class in public API because we do not (yet) guarantee
  * than all conformal projections will extend this base class.
@@ -45,6 +41,12 @@ import static java.lang.Math.*;
  * appear to be the same with the <var>n</var> factor fixed to 1 or -1, so we leverage the code provided by
  * this base class. This class hierarchy is only an implementation convenience and not part of public API.</p>
  *
+ * <div class="note"><b>Reference:</b>
+ * “Lambert developed the regular Conformal Conic as the oblique aspect of a family containing the previously
+ * known polar Stereographic and regular Mercator projections. (…) If the standard parallels are symmetrical
+ * about the Equator, the regular Mercator results (although formulas must be revised). If the only standard
+ * parallel is a pole, the polar Stereographic results.” (Snyder, page 105)</div>
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
  * @version 0.6
@@ -101,17 +103,12 @@ abstract class ConformalProjection exten
     private transient boolean useIterations;
 
     /**
-     * Constructs a new map projection from the supplied parameters.
+     * Creates a new normalized projection from the parameters computed by the given initializer.
      *
-     * @param method     Description of the map projection parameters.
-     * @param parameters The parameters of the projection to be created.
-     * @param roles Parameters to look for <cite>central meridian</cite>, <cite>scale factor</cite>,
-     *        <cite>false easting</cite>, <cite>false northing</cite> and other values.
-     */
-    protected ConformalProjection(final OperationMethod method, final Parameters parameters,
-            final Map<ParameterRole, ? extends ParameterDescriptor<Double>> roles)
-    {
-        super(method, parameters, roles);
+     * @param initializer The initializer for computing map projection internal parameters.
+     */
+    ConformalProjection(final Initializer initializer) {
+        super(initializer);
         initialize();
     }
 



Mime
View raw message