Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java?rev=1693439&r1=1693438&r2=1693439&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java [UTF-8] Thu Jul 30 15:27:52 2015 @@ -16,7 +16,6 @@ */ package org.apache.sis.referencing.operation.projection; -import java.util.Map; import java.util.EnumMap; import org.opengis.util.FactoryException; import org.opengis.parameter.ParameterDescriptor; @@ -30,6 +29,7 @@ import org.apache.sis.internal.referenci import org.apache.sis.internal.referencing.provider.PolarStereographicB; import org.apache.sis.internal.referencing.provider.PolarStereographicC; import org.apache.sis.internal.referencing.Formulas; +import org.apache.sis.internal.util.DoubleDouble; import org.apache.sis.parameter.Parameters; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.Workaround; @@ -86,12 +86,30 @@ public class PolarStereographic extends } /** - * Returns the (<var>role</var> → <var>parameter</var>) associations for a Polar Stereographic projection. + * Creates a Polar Stereographic projection from the given parameters. + * The {@code method} argument can be the description of one of the following: + * + * <ul> + * <li><cite>"Polar Stereographic (Variant A)"</cite>.</li> + * <li><cite>"Polar Stereographic (Variant B)"</cite>.</li> + * <li><cite>"Polar Stereographic (Variant C)"</cite>.</li> + * </ul> * - * @param variant One of {@link #A}, {@link #B}, {@link #C}, {@link #NORTH} or {@link #SOUTH} constants. - * @return The roles map to give to super-class constructor. + * @param method Description of the projection parameters. + * @param parameters The parameter values of the projection to create. */ - private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final byte variant) { + public PolarStereographic(final OperationMethod method, final Parameters parameters) { + this(initializer(method, parameters)); + } + + /** + * Work around for RFE #4093999 in Sun's bug database + * ("Relax constraint on placement of this()/super() call in constructors"). + */ + @SuppressWarnings("fallthrough") + @Workaround(library="JDK", version="1.7") + private static Initializer initializer(final OperationMethod method, final Parameters parameters) { + final byte variant = getVariant(method); final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new EnumMap<>(ParameterRole.class); ParameterDescriptor<Double> falseEasting = PolarStereographicA.FALSE_EASTING; ParameterDescriptor<Double> falseNorthing = PolarStereographicA.FALSE_NORTHING; @@ -105,24 +123,7 @@ public class PolarStereographic extends roles.put(ParameterRole.CENTRAL_MERIDIAN, (variant == A) ? PolarStereographicA.LONGITUDE_OF_ORIGIN : PolarStereographicB.LONGITUDE_OF_ORIGIN); - return roles; - } - - /** - * Creates a Polar Stereographic projection from the given parameters. - * The {@code method} argument can be the description of one of the following: - * - * <ul> - * <li><cite>"Polar Stereographic (Variant A)"</cite>.</li> - * <li><cite>"Polar Stereographic (Variant B)"</cite>.</li> - * <li><cite>"Polar Stereographic (Variant C)"</cite>.</li> - * </ul> - * - * @param method Description of the projection parameters. - * @param parameters The parameter values of the projection to create. - */ - public PolarStereographic(final OperationMethod method, final Parameters parameters) { - this(method, parameters, getVariant(method)); + return new Initializer(method, parameters, roles, variant); } /** @@ -130,8 +131,9 @@ public class PolarStereographic extends * ("Relax constraint on placement of this()/super() call in constructors"). */ @Workaround(library="JDK", version="1.7") - private PolarStereographic(final OperationMethod method, final Parameters parameters, final byte variant) { - super(method, parameters, roles(variant)); + private PolarStereographic(final Initializer initializer) { + super(initializer); + final byte variant = initializer.variant; /* * "Standard parallel" and "Latitude of origin" should be mutually exclusive, * but this is not a strict requirement for the constructor. @@ -149,9 +151,9 @@ public class PolarStereographic extends */ double φ0; if (variant == A) { - φ0 = getAndStore(parameters, PolarStereographicA.LATITUDE_OF_ORIGIN); // Mandatory + φ0 = initializer.getAndStore(PolarStereographicA.LATITUDE_OF_ORIGIN); // Mandatory } else { - φ0 = getAndStore(parameters, PolarStereographicA.LATITUDE_OF_ORIGIN, // Optional (should not be present) + φ0 = initializer.getAndStore(PolarStereographicA.LATITUDE_OF_ORIGIN, // Optional (should not be present) (variant == NORTH) ? Latitude.MAX_VALUE : (variant == SOUTH) ? Latitude.MIN_VALUE : Double.NaN); } @@ -161,9 +163,9 @@ public class PolarStereographic extends } double φ1; if (variant == B || variant == C || Double.isNaN(φ0)) { - φ1 = getAndStore(parameters, PolarStereographicB.STANDARD_PARALLEL); // Mandatory + φ1 = initializer.getAndStore(PolarStereographicB.STANDARD_PARALLEL); // Mandatory } else { - φ1 = getAndStore(parameters, PolarStereographicB.STANDARD_PARALLEL, φ0); // Optional + φ1 = initializer.getAndStore(PolarStereographicB.STANDARD_PARALLEL, φ0); // Optional } /* * At this point we should ensure that the sign of φ0 is the same than the sign of φ1, @@ -183,8 +185,8 @@ public class PolarStereographic extends φ1 = -φ1; } φ1 = toRadians(φ1); // May be anything in [-π/2 … 0] range. - final double ρ; - Double ρF = null; // Actually -ρF (compared to EPSG guide). + final DoubleDouble ρ; + DoubleDouble ρF = null; // Actually -ρF (compared to EPSG guide). if (abs(φ1 + PI/2) < ANGULAR_TOLERANCE) { /* * Polar Stereographic (variant A) @@ -197,8 +199,19 @@ public class PolarStereographic extends * - the 't' factor, because it needs to be computed in the transform(…) method. * * In the spherical case, should give ρ == 2. + * + * Opportunistically use double-double arithmetic below since this is what we will store in the + * (de)normalization matrices. The extra precision that we get is not necessarily significant, + * but we do that more in an attempt to reduce rounding errors in concatenations of a sequence + * of MathTransforms (through matrix multiplications) than for map projection precisions. + * Equivalent Java code for the following double-double arithmetic: + * + * ρ = 2 / sqrt(pow(1+excentricity, 1+excentricity) * pow(1-excentricity, 1-excentricity)); */ - ρ = 2 / sqrt(pow(1+excentricity, 1+excentricity) * pow(1-excentricity, 1-excentricity)); + ρ = new DoubleDouble(pow(1+excentricity, 1+excentricity), 0); + ρ.multiply (pow(1-excentricity, 1-excentricity), 0); + ρ.sqrt(); + ρ.inverseDivide(2, 0); } else { /* * Polar Stereographic (variant B or C) @@ -216,13 +229,21 @@ public class PolarStereographic extends * k₀ = ρ⋅√[…]/2 but we do not need that value. * * In the spherical case, should give ρ = 1 + sinφ1 (Synder 21-7 and 21-11). + * + * Equivalent Java code for the following double-double arithmetic: + * + * final double mF = cos(φ1) / rν(sinφ1); + * ρ = mF / expOfNorthing(φ1, excentricity*sinφ1); + * if (variant == C) ρF = -mF; */ final double sinφ1 = sin(φ1); - final double mF = cos(φ1) / rν(sinφ1); - ρ = mF / expOfNorthing(φ1, excentricity*sinφ1); + ρ = initializer.rν(sinφ1); + ρ.inverseDivide(cos(φ1), 0); if (variant == C) { - ρF = -mF; + ρF = new DoubleDouble(ρ); + ρF.negate(); } + ρ.divide(expOfNorthing(φ1, excentricity*sinφ1), 0); } /* * At this point, all parameters have been processed. Now process to their
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java?rev=1693439&r1=1693438&r2=1693439&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java [UTF-8] Thu Jul 30 15:27:52 2015 @@ -16,7 +16,6 @@ */ package org.apache.sis.referencing.operation.projection; -import java.util.Map; import java.util.EnumMap; import org.opengis.parameter.ParameterDescriptor; import org.opengis.referencing.operation.Matrix; @@ -27,6 +26,7 @@ import org.apache.sis.internal.referenci import org.apache.sis.internal.util.DoubleDouble; import org.apache.sis.parameter.Parameters; import org.apache.sis.util.resources.Errors; +import org.apache.sis.util.Workaround; import static java.lang.Math.*; import static org.apache.sis.math.MathFunctions.asinh; @@ -72,11 +72,29 @@ public class TransverseMercator extends private final double h1, h2, h3, h4, ih1, ih2, ih3, ih4; /** - * Returns the (<var>role</var> → <var>parameter</var>) associations for a Transverse Mercator projection. + * Creates a Transverse Mercator projection from the given parameters. + * The {@code method} argument can be the description of one of the following: + * + * <ul> + * <li><cite>"Transverse Mercator"</cite>.</li> + * <li><cite>"Transverse Mercator (South Orientated)"</cite>.</li> + * </ul> * - * @return The roles map to give to super-class constructor. + * @param method Description of the projection parameters. + * @param parameters The parameter values of the projection to create. */ - private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final boolean isSouth) { + public TransverseMercator(final OperationMethod method, final Parameters parameters) { + this(initializer(method, parameters)); + } + + /** + * Work around for RFE #4093999 in Sun's bug database + * ("Relax constraint on placement of this()/super() call in constructors"). + */ + @SuppressWarnings("fallthrough") + @Workaround(library="JDK", version="1.7") + private static Initializer initializer(final OperationMethod method, final Parameters parameters) { + final boolean isSouth = identMatch(method, "(?i).*\\bSouth\\b.*", TransverseMercatorSouth.IDENTIFIER); final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new EnumMap<>(ParameterRole.class); ParameterRole xOffset = ParameterRole.FALSE_EASTING; ParameterRole yOffset = ParameterRole.FALSE_NORTHING; @@ -88,34 +106,20 @@ public class TransverseMercator extends roles.put(ParameterRole.SCALE_FACTOR, org.apache.sis.internal.referencing.provider.TransverseMercator.SCALE_FACTOR); roles.put(xOffset, org.apache.sis.internal.referencing.provider.TransverseMercator.FALSE_EASTING); roles.put(yOffset, org.apache.sis.internal.referencing.provider.TransverseMercator.FALSE_NORTHING); - return roles; + return new Initializer(method, parameters, roles, isSouth ? (byte) 1 : (byte) 0); } /** - * Returns the type of the projection based on the name and identifier of the given operation method. + * Work around for RFE #4093999 in Sun's bug database + * ("Relax constraint on placement of this()/super() call in constructors"). */ - private static boolean isSouth(final OperationMethod method) { - return identMatch(method, "(?i).*\\bSouth\\b.*", TransverseMercatorSouth.IDENTIFIER); - } - - /** - * Creates a Transverse Mercator projection from the given parameters. - * The {@code method} argument can be the description of one of the following: - * - * <ul> - * <li><cite>"Transverse Mercator"</cite>.</li> - * <li><cite>"Transverse Mercator (South Orientated)"</cite>.</li> - * </ul> - * - * @param method Description of the projection parameters. - * @param parameters The parameter values of the projection to create. - */ - public TransverseMercator(final OperationMethod method, final Parameters parameters) { - super(method, parameters, roles(isSouth(method))); - final double φ0 = toRadians(getAndStore(parameters, + @Workaround(library="JDK", version="1.7") + private TransverseMercator(final Initializer initializer) { + super(initializer); + final double φ0 = toRadians(initializer.getAndStore( org.apache.sis.internal.referencing.provider.TransverseMercator.LATITUDE_OF_ORIGIN)); - final double rs = parameters.doubleValue(MapProjection.SEMI_MINOR) - / parameters.doubleValue(MapProjection.SEMI_MAJOR); + final double rs = initializer.parameters.doubleValue(MapProjection.SEMI_MINOR) + / initializer.parameters.doubleValue(MapProjection.SEMI_MAJOR); final double n = (1 - rs) / (1 + rs); // Rewrite of n = f / (2-f) final double n2 = n * n; Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java?rev=1693439&r1=1693438&r2=1693439&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java [UTF-8] Thu Jul 30 15:27:52 2015 @@ -87,7 +87,7 @@ public final strictfp class LambertConic createNormalizedProjection(true, 40); assertWktEqualsRegex("\\Q" + "PARAM_MT[“Lambert conic conformal”,\n" + - " PARAMETER[“excentricity”, 0.08181919084262157],\n" + + " PARAMETER[“excentricity”, 0.08181919084262244],\n" + " PARAMETER[“n”, 0.64278760968653\\E\\d*\\]\\]"); // 0.6427876096865393 in the original test. } Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java?rev=1693439&r1=1693438&r2=1693439&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java [UTF-8] Thu Jul 30 15:27:52 2015 @@ -75,7 +75,7 @@ public final strictfp class MercatorTest createNormalizedProjection(true); assertWktEquals( "PARAM_MT[“Mercator”,\n" + - " PARAMETER[“excentricity”, 0.08181919084262157]]"); + " PARAMETER[“excentricity”, 0.08181919084262244]]"); } /** Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java?rev=1693439&r1=1693438&r2=1693439&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java [UTF-8] (original) +++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java [UTF-8] Thu Jul 30 15:27:52 2015 @@ -61,9 +61,9 @@ final strictfp class NoOp extends Confor */ @Workaround(library="JDK", version="1.7") private NoOp(final Parameters parameters) { - super(new DefaultOperationMethod( + super(new Initializer(new DefaultOperationMethod( Collections.singletonMap(DefaultOperationMethod.NAME_KEY, parameters.getDescriptor().getName()), - 2, 2, parameters.getDescriptor()), parameters, Collections.emptyMap()); + 2, 2, parameters.getDescriptor()), parameters, Collections.emptyMap(), (byte) 0)); } /**
