Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -20,7 +20,6 @@ import java.util.Map; import java.util.EnumMap; import org.opengis.util.FactoryException; import org.opengis.parameter.ParameterDescriptor; -import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.referencing.operation.Matrix; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransformFactory; @@ -76,23 +75,38 @@ import static org.apache.sis.math.MathFu * @see TransverseMercator * @see ObliqueMercator */ -public class Mercator extends AbstractLambertConformal { +public class Mercator extends ConformalProjection { /** * For cross-version compatibility. */ private static final long serialVersionUID = 2564172914329253286L; /** - * Codes for special kinds of Mercator projection. We do not provide such codes in public API because - * they duplicate the functionality of {@link OperationMethod} instances. We use them only for convenience. + * Codes for variants of Mercator projection. Those variants modify the way the projections are constructed + * (e.g. in the way parameters are interpreted), but formulas are basically the same after construction. + * Those variants are not exactly the same than variants A, B and C used by EPSG, but they are related. * - * <p><b>CONVENTION:</b> Spherical cases must be odd, all other cases must be even. This allow us to perform - * quick checks for all spherical cases using {@code if ((type & SPHERICAL) != 0)}.</p> + * <p>We do not provide such codes in public API because they duplicate the functionality of + * {@link OperationMethod} instances. We use them only for constructors convenience.</p> * - * @see #getType(ParameterDescriptorGroup) + * <p><b>CONVENTION:</b> <strong>Spherical cases must be odd, all other cases must be even.</strong> + * This allow us to perform quick checks for all spherical cases using {@code if ((type & SPHERICAL) != 0)}.</p> + * + * @see #getVariant(OperationMethod) + */ + private static final byte SPHERICAL = 1, PSEUDO = 3, // Must be odd and SPHERICAL must be 1. + REGIONAL = 2, MILLER = 4; // Must be even. + + /** + * Returns the variant of the projection based on the name and identifier of the given operation method. */ - static final byte SPHERICAL = 1, PSEUDO = 3, // Must be odd and SPHERICAL must be 1. - REGIONAL = 2, MILLER = 4; // Must be even. + private static byte getVariant(final OperationMethod method) { + if (identMatch(method, "(?i).*\\bvariant\\s*C\\b.*", RegionalMercator .IDENTIFIER)) return REGIONAL; + if (identMatch(method, "(?i).*\\bSpherical\\b.*", MercatorSpherical.IDENTIFIER)) return SPHERICAL; + if (identMatch(method, "(?i).*\\bPseudo.*", PseudoMercator .IDENTIFIER)) return PSEUDO; + if (identMatch(method, "(?i).*\\bMiller.*", null)) return MILLER; + return 0; + } /** * The type of Mercator projection. Possible values are: @@ -106,18 +120,18 @@ public class Mercator extends AbstractLa * * Other cases may be added in the future. * - * @see #getType(ParameterDescriptorGroup) + * @see #getVariant(OperationMethod) */ - final byte type; + private final byte variant; /** - * Returns the (<var>role</var> → <var>parameter</var>) associations for a Mercator projection of the given type. + * Returns the (<var>role</var> → <var>parameter</var>) associations for a Mercator projection of the given variant. * - * @param type One of {@link #REGIONAL}, {@link #SPHERICAL}, {@link #PSEUDO} or {@link #MILLER} constants. + * @param variant One of {@link #REGIONAL}, {@link #SPHERICAL}, {@link #PSEUDO} or {@link #MILLER} constants. * @return The roles map to give to super-class constructor. */ @SuppressWarnings("fallthrough") - private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final byte type) { + private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final byte variant) { final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new EnumMap<ParameterRole, ParameterDescriptor<Double>>(ParameterRole.class); /* @@ -127,7 +141,7 @@ public class Mercator extends AbstractLa * since it may be used in some Well Known Text (WKT). */ roles.put(ParameterRole.SCALE_FACTOR, Mercator1SP.SCALE_FACTOR); - switch (type) { + switch (variant) { case REGIONAL: { roles.put(ParameterRole.FALSE_EASTING, RegionalMercator.EASTING_AT_FALSE_ORIGIN); roles.put(ParameterRole.FALSE_NORTHING, RegionalMercator.NORTHING_AT_FALSE_ORIGIN); @@ -178,7 +192,7 @@ public class Mercator extends AbstractLa * @param parameters The parameter values of the projection to create. */ public Mercator(final OperationMethod method, final Parameters parameters) { - this(method, parameters, getType(parameters.getDescriptor())); + this(method, parameters, getVariant(method)); } /** @@ -186,15 +200,15 @@ public class Mercator extends AbstractLa * ("Relax constraint on placement of this()/super() call in constructors"). */ @Workaround(library="JDK", version="1.7") - private Mercator(final OperationMethod method, final Parameters parameters, final byte type) { - super(method, parameters, roles(type)); - this.type = type; + private Mercator(final OperationMethod method, final Parameters parameters, final byte variant) { + super(method, parameters, roles(variant)); + this.variant = variant; /* * The "Longitude of natural origin" parameter is found in all Mercator projections and is mandatory. * Since this is usually the Greenwich meridian, the default value is 0°. We keep the value in degrees * for now; it will be converted to radians later. */ - final double λ0 = getAndStore(parameters, Mercator1SP.CENTRAL_MERIDIAN); + final double λ0 = getAndStore(parameters, Mercator1SP.LONGITUDE_OF_ORIGIN); /* * The "Latitude of natural origin" is not formally a parameter of Mercator projection. But the parameter * is included for completeness in CRS labelling, with the restriction (specified in EPSG documentation) @@ -207,7 +221,7 @@ public class Mercator extends AbstractLa * "Latitude of origin" can not have a non-zero value, if it still have non-zero value we will process as * for "Latitude of false origin". */ - final double φ0 = toRadians(getAndStore(parameters, (type == REGIONAL) + final double φ0 = toRadians(getAndStore(parameters, (variant == REGIONAL) ? RegionalMercator.LATITUDE_OF_FALSE_ORIGIN : Mercator1SP.LATITUDE_OF_ORIGIN)); /* * In theory, the "Latitude of 1st standard parallel" and the "Scale factor at natural origin" parameters @@ -241,7 +255,7 @@ public class Mercator extends AbstractLa if (φ0 != 0) { denormalize.convertBefore(1, null, new DoubleDouble(-log(expOfNorthing(φ0, excentricity * sin(φ0))))); } - if (type == MILLER) { + if (variant == MILLER) { normalize.convertBefore(1, new DoubleDouble(0.80), null); denormalize.convertBefore(1, new DoubleDouble(1.25), null); } @@ -280,18 +294,7 @@ public class Mercator extends AbstractLa */ Mercator(final Mercator other) { super(other); - type = other.type; - } - - /** - * Returns the type of the projection based on the name and identifier of the given parameter group. - */ - private static byte getType(final ParameterDescriptorGroup parameters) { - if (identMatch(parameters, "(?i).*\\bvariant\\s*C\\b.*", RegionalMercator .IDENTIFIER)) return REGIONAL; - if (identMatch(parameters, "(?i).*\\bSpherical\\b.*", MercatorSpherical.IDENTIFIER)) return SPHERICAL; - if (identMatch(parameters, "(?i).*\\bPseudo.*", PseudoMercator .IDENTIFIER)) return PSEUDO; - if (identMatch(parameters, "(?i).*\\bMiller.*", null)) return MILLER; - return 0; + variant = other.variant; } /** @@ -309,7 +312,7 @@ public class Mercator extends AbstractLa @Override public MathTransform createMapProjection(final MathTransformFactory factory) throws FactoryException { Mercator kernel = this; - if ((type & SPHERICAL) != 0 || excentricity == 0) { + if ((variant & SPHERICAL) != 0 || excentricity == 0) { kernel = new Spherical(this); } return context.completeTransform(factory, kernel); @@ -329,29 +332,28 @@ public class Mercator extends AbstractLa final double[] dstPts, final int dstOff, final boolean derivate) throws ProjectionException { - final double λ = srcPts[srcOff]; - final double φ = srcPts[srcOff + 1]; + final double φ = srcPts[srcOff+1]; final double sinφ = sin(φ); - /* - * Projection of zero is zero. However the formulas below have a slight rounding error - * which produce values close to 1E-10, so we will avoid them when y=0. In addition of - * avoiding rounding error, this also preserve the sign (positive vs negative zero). - */ - final double y; - if (φ == 0) { - y = φ; - } else { - // See the javadoc of the Spherical inner class for a note - // about why we perform explicit checks for the pole cases. - final double a = abs(φ); - if (a < PI/2) { - y = log(expOfNorthing(φ, excentricity * sinφ)); // Snyder (7-7) + if (dstPts != null) { + /* + * Projection of zero is zero. However the formulas below have a slight rounding error + * which produce values close to 1E-10, so we will avoid them when y=0. In addition of + * avoiding rounding error, this also preserve the sign (positive vs negative zero). + */ + final double y; + if (φ == 0) { + y = φ; } else { - y = copySign(a <= (PI/2 + ANGULAR_TOLERANCE) ? POSITIVE_INFINITY : NaN, φ); + // See the javadoc of the Spherical inner class for a note + // about why we perform explicit checks for the pole cases. + final double a = abs(φ); + if (a < PI/2) { + y = log(expOfNorthing(φ, excentricity * sinφ)); // Snyder (7-7) + } else { + y = copySign(a <= (PI/2 + ANGULAR_TOLERANCE) ? POSITIVE_INFINITY : NaN, φ); + } } - } - if (dstPts != null) { - dstPts[dstOff] = λ; + dstPts[dstOff ] = srcPts[srcOff]; // Scale will be applied by the denormalization matrix. dstPts[dstOff+1] = y; } /* @@ -462,40 +464,29 @@ public class Mercator extends AbstractLa final double[] dstPts, final int dstOff, final boolean derivate) throws ProjectionException { - final double λ = srcPts[srcOff ]; final double φ = srcPts[srcOff+1]; - /* - * Projection of zero is zero. However the formulas below have a slight rounding error - * which produce values close to 1E-10, so we will avoid them when y=0. In addition of - * avoiding rounding error, this also preserve the sign (positive vs negative zero). - */ - final double y; - if (φ == 0) { - y = φ; - } else { - // See class javadoc for a note about explicit check for poles. - final double a = abs(φ); - if (a < PI/2) { - y = log(tan(PI/4 + 0.5*φ)); // Part of Snyder (7-2) + if (dstPts != null) { + /* + * Projection of zero is zero. However the formulas below have a slight rounding error + * which produce values close to 1E-10, so we will avoid them when y=0. In addition of + * avoiding rounding error, this also preserve the sign (positive vs negative zero). + */ + final double y; + if (φ == 0) { + y = φ; } else { - y = copySign(a <= (PI/2 + ANGULAR_TOLERANCE) ? POSITIVE_INFINITY : NaN, φ); + // See class javadoc for a note about explicit check for poles. + final double a = abs(φ); + if (a < PI/2) { + y = log(tan(PI/4 + 0.5*φ)); // Part of Snyder (7-2) + } else { + y = copySign(a <= (PI/2 + ANGULAR_TOLERANCE) ? POSITIVE_INFINITY : NaN, φ); + } } - } - Matrix derivative = null; - if (derivate) { - derivative = new Matrix2(1, 0, 0, 1/cos(φ)); - } - /* - * Following part is common to all spherical projections: verify, store and return. - */ - assert (excentricity != 0) // Can not perform the following assertions if excentricity is not zero. - || (Assertions.checkDerivative(derivative, super.transform(srcPts, srcOff, dstPts, dstOff, derivate)) - && Assertions.checkTransform(dstPts, dstOff, λ, y)); // dstPts = result from ellipsoidal formulas. - if (dstPts != null) { - dstPts[dstOff ] = λ; + dstPts[dstOff ] = srcPts[srcOff]; dstPts[dstOff+1] = y; } - return derivative; + return derivate ? new Matrix2(1, 0, 0, 1/cos(φ)) : null; } /** @@ -539,26 +530,9 @@ public class Mercator extends AbstractLa final double[] dstPts, final int dstOff) throws ProjectionException { - double x = srcPts[srcOff ]; - double y = srcPts[srcOff+1]; - y = PI/2 - 2 * atan(exp(-y)); // Part of Snyder (7-4) - assert (excentricity != 0) // Can not perform the following assertion if excentricity is not zero. - || checkInverseTransform(srcPts, srcOff, dstPts, dstOff, x, y); - dstPts[dstOff ] = x; - dstPts[dstOff+1] = y; - } - - /** - * Computes using ellipsoidal formulas and compare with the - * result from spherical formulas. Used in assertions only. - */ - private boolean checkInverseTransform(final double[] srcPts, final int srcOff, - final double[] dstPts, final int dstOff, - final double λ, final double φ) - throws ProjectionException - { - super.inverseTransform(srcPts, srcOff, dstPts, dstOff); - return Assertions.checkInverseTransform(dstPts, dstOff, λ, φ); + final double y = srcPts[srcOff+1]; // Must be before writing x. + dstPts[dstOff ] = srcPts[srcOff]; // Must be before writing y. + dstPts[dstOff+1] = PI/2 - 2*atan(exp(-y)); // Part of Snyder (7-4); } } }
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -143,7 +143,7 @@ public abstract class NormalizedProjecti /** * Desired accuracy for the result of iterative computations, in radians. - * This constant defines the desired accuracy of methods like {@link AbstractLambertConformal#φ(double)}. + * This constant defines the desired accuracy of methods like {@link ConformalProjection#φ(double)}. * * <p>The current value is 0.25 time the accuracy derived from {@link Formulas#LINEAR_TOLERANCE}. * So if the linear tolerance is 1 cm, then the accuracy that we will seek for is 0.25 cm (about @@ -453,7 +453,7 @@ public abstract class NormalizedProjecti } /** - * Returns {@code true} if the projection specified by the given parameters has the given keyword or identifier. + * Returns {@code true} if the projection specified by the given method has the given keyword or identifier. * If non-null, the given identifier is presumed in the EPSG namespace and has precedence over the keyword. * * <div class="note"><b>Implementation note:</b> @@ -464,19 +464,19 @@ public abstract class NormalizedProjecti * * @param parameters The user-specified parameters. * @param regex The regular expression to use when using the operation name as the criterion. - * @param identifier The identifier to compare against the parameter group name. - * @return {@code true} if the given parameter group name contains the given keyword + * @param identifier The identifier to compare against the operation method name. + * @return {@code true} if the name of the given operation method contains the given keyword * or has an EPSG identifier equals to the given identifier. */ - static boolean identMatch(final ParameterDescriptorGroup parameters, final String regex, final String identifier) { + static boolean identMatch(final OperationMethod method, final String regex, final String identifier) { if (identifier != null) { - for (final ReferenceIdentifier id : parameters.getIdentifiers()) { + for (final ReferenceIdentifier id : method.getIdentifiers()) { if (Constants.EPSG.equals(id.getCodeSpace())) { return identifier.equals(id.getCode()); } } } - return parameters.getName().getCode().matches(regex); + return method.getName().getCode().replace('_',' ').matches(regex); } /** @@ -501,7 +501,7 @@ public abstract class NormalizedProjecti final Double defaultValue = descriptor.getDefaultValue(); if (defaultValue == null || !defaultValue.equals(value)) { MapProjection.validate(descriptor, value); - context.parameter(descriptor.getName().getCode()).setValue(value); + context.getOrCreate(descriptor).setValue(value); } return value; } @@ -861,91 +861,4 @@ public abstract class NormalizedProjecti final double rν(final double sinφ) { return sqrt(1 - excentricitySquared * (sinφ*sinφ)); } - - /** - * Computes part of the Mercator projection for the given latitude. This formula is also part of - * Lambert Conic Conformal projection, since Mercator can be considered as a special case of that - * Lambert projection with the equator as the single standard parallel. - * - * <p>The Mercator projection is given by the {@linkplain Math#log(double) natural logarithm} - * of the value returned by this method. This function is <em>almost</em> the converse of - * {@link AbstractLambertConformal#φ(double)}. - * - * <p>In IOGP Publication 373-7-2 – Geomatics Guidance Note number 7, part 2 – April 2015, - * a function closely related to this one has the letter <var>t</var>.</p> - * - * - * <div class="section">Properties</div> - * This function is used with φ values in the [-π/2 … π/2] range and has a periodicity of 2π. - * The result is always a positive number when the φ argument is inside the above-cited range. - * If, after removal of any 2π periodicity, φ is still outside the [-π/2 … π/2] range, then the - * result is a negative number. In a Mercator projection, such negative number will result in NaN. - * - * <p>Some values are:</p> - * <ul> - * <li>expOfNorthing(NaN) = NaN</li> - * <li>expOfNorthing(±∞) = NaN</li> - * <li>expOfNorthing(-π/2) = 0</li> - * <li>expOfNorthing( 0 ) = 1</li> - * <li>expOfNorthing(+π/2) → ∞ (actually some large value like 1.633E+16)</li> - * <li>expOfNorthing(-φ) = 1 / expOfNorthing(φ)</li> - * </ul> - * - * - * <div class="section">The π/2 special case</div> - * The value at {@code Math.PI/2} is not exactly infinity because there is no exact representation of π/2. - * However since the conversion of 90° to radians gives {@code Math.PI/2}, we can presume that the user was - * expecting infinity. The caller should check for the PI/2 special case himself if desired, as this method - * does nothing special about it. - * - * <p>Note that the result for the φ value after {@code Math.PI/2} (as given by {@link Math#nextUp(double)}) - * is still positive, maybe because {@literal PI/2 < π/2 < nextUp(PI/2)}. Only the {@code nextUp(nextUp(PI/2))} - * value become negative. Callers may need to take this behavior in account: special check for {@code Math.PI/2} - * is not sufficient, the check needs to include at least the {@code nextUp(Math.PI/2)} case.</p> - * - * - * <div class="section">Relationship with Snyder</div> - * This function is related to the following functions from Snyder: - * - * <ul> - * <li>(7-7) in the <cite>Mercator projection</cite> chapter.</li> - * <li>Reciprocal of (9-13) in the <cite>Oblique Mercator projection</cite> chapter.</li> - * <li>Reciprocal of (15-9) in the <cite>Lambert Conformal Conic projection</cite> chapter.</li> - * </ul> - * - * @param φ The latitude in radians. - * @param ℯsinφ The sine of the φ argument multiplied by {@link #excentricity}. - * @return {@code Math.exp} of the Mercator projection of the given latitude. - * - * @see AbstractLambertConformal#φ(double) - * @see #dy_dφ(double, double) - */ - final double expOfNorthing(final double φ, final double ℯsinφ) { - /* - * Note: tan(π/4 - φ/2) = 1 / tan(π/4 + φ/2) - * - * A + sign in the equation favorises slightly the accuracy in South hemisphere, while a - sign - * favorises slightly the North hemisphere (but the differences are very small). In Apache SIS, - * we handle that by changing the sign of some terms in the (de)normalisation matrices. - */ - return tan(PI/4 + 0.5*φ) * pow((1 - ℯsinφ) / (1 + ℯsinφ), 0.5*excentricity); - } - - /** - * Computes the partial derivative of a Mercator projection at the given latitude. This formula is also part of - * other projections, since Mercator can be considered as a special case of Lambert Conic Conformal for instance. - * - * <p>In order to get the derivative of the {@link #expOfNorthing(double, double)} function, call can multiply - * the returned value by by {@code expOfNorthing}.</p> - * - * @param sinφ the sine of latitude. - * @param cosφ The cosine of latitude. - * @return The partial derivative of a Mercator projection at the given latitude. - * - * @see #expOfNorthing(double, double) - * @see AbstractLambertConformal#φ(double) - */ - final double dy_dφ(final double sinφ, final double cosφ) { - return (1 / cosφ) - excentricitySquared * cosφ / (1 - excentricitySquared * (sinφ*sinφ)); - } } Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -40,6 +40,7 @@ import org.apache.sis.util.resources.Err * @version 0.6 * @module */ +@SuppressWarnings("CloneInNonCloneableClass") abstract class AbstractLinearTransform extends AbstractMathTransform implements LinearTransform, Matrix // Not Cloneable, despite the clone() method. { Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -99,6 +99,7 @@ class ConcatenatedTransform extends Abst * @param transform1 The first math transform. * @param transform2 The second math transform. */ + @SuppressWarnings("OverridableMethodCallDuringObjectConstruction") protected ConcatenatedTransform(final MathTransform transform1, final MathTransform transform2) { Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -370,6 +370,7 @@ public class ContextualParameters extend * * @see org.apache.sis.referencing.operation.projection.NormalizedProjection#createMapProjection(MathTransformFactory) */ + @SuppressWarnings("AssignmentToForLoopParameter") public MathTransform completeTransform(final MathTransformFactory factory, final MathTransform kernel) throws FactoryException { Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -26,7 +26,6 @@ import org.apache.sis.referencing.operat import org.apache.sis.referencing.operation.matrix.Matrices; - /** * A transform which copy the ordinates in the source array to different locations in the target array. * This is a special case of {@link ProjectiveTransform} where the matrix coefficients are zero everywhere, Modified: sis/trunk/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] Tue Jul 21 16:57:38 2015 @@ -14,3 +14,8 @@ org.apache.sis.internal.referencing.prov org.apache.sis.internal.referencing.provider.LambertConformalWest org.apache.sis.internal.referencing.provider.LambertConformalBelgium org.apache.sis.internal.referencing.provider.LambertConformalMichigan +org.apache.sis.internal.referencing.provider.PolarStereographicA +org.apache.sis.internal.referencing.provider.PolarStereographicB +org.apache.sis.internal.referencing.provider.PolarStereographicC +org.apache.sis.internal.referencing.provider.PolarStereographicNorth +org.apache.sis.internal.referencing.provider.PolarStereographicSouth Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -141,7 +141,7 @@ public final strictfp class MapProjectio * This test is mostly for {@link Equirectangular#LATITUDE_OF_ORIGIN}. */ private static void assertIsForcedToZero(final ParameterDescriptor<?> parameter) { - final Double zero = Double.valueOf(0); + final Double zero = 0.0; assertEquals("minimumValue", zero, parameter.getMinimumValue()); assertEquals("maximumValue", zero, parameter.getMaximumValue()); } Copied: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java (from r1692168, sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java?p2=sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java&p1=sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java&r1=1692168&r2=1692172&rev=1692172&view=diff ============================================================================== --- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConformalProjectionTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -202,20 +202,6 @@ public final strictfp class ConformalPro return projection.dy_dφ(sinφ, cos(φ)) * expOfNorthing(projection, φ); } }; - verifyInDomain(-89 * (PI/180), 89 * (PI/180)); // Verify from 85°S to 85°N. - } - - /** - * Convenience method invoking {@link TransformTestCase#verifyInDomain} for an 1D transform. - */ - private void verifyInDomain(final double min, final double max) throws TransformException { - derivativeDeltas = new double[] {2E-8}; - isInverseTransformSupported = false; - verifyInDomain( - new double[] {min}, // Minimal value to test. - new double[] {max}, // Maximal value to test. - new int[] {100}, // Number of points to test. - TestUtilities.createRandomNumberGenerator()); } /** Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -44,11 +44,11 @@ import static org.apache.sis.internal.me public final strictfp class EquirectangularTest extends MapProjectionTestCase { /** * Initializes a simple Equirectangular projection on sphere. This method is different than the - * {@code initialize(boolean)} method in all other test classes, because it does not create an - * instance of {@link NormalizedProjection}. Instead, it creates an affine transform for the - * whole projection (not only the normalized part). + * {@code createNormalizedProjection(boolean)} method in all other test classes, because it does + * not create an instance of {@link NormalizedProjection}. Instead, it creates an affine transform + * for the whole projection (not only the normalized part). */ - private void initialize() throws FactoryException { + private void createCompleteProjection() throws FactoryException { final Equirectangular provider = new Equirectangular(); final Parameters parameters = parameters(provider, false); transform = new MathTransformFactoryMock(provider).createParameterizedTransform(parameters); @@ -65,7 +65,7 @@ public final strictfp class Equirectangu */ @Test public void testWKT() throws FactoryException { - initialize(); + createCompleteProjection(); assertWktEquals( "PARAM_MT[“Equirectangular”,\n" + " PARAMETER[“semi_major”, 6371007.0],\n" + @@ -95,7 +95,7 @@ public final strictfp class Equirectangu */ @Test public void testSimpleTransform() throws FactoryException, TransformException { - initialize(); + createCompleteProjection(); verifyTransform( new double[] { // (λ,φ) coordinates in degrees to project. 0, 0, @@ -118,7 +118,7 @@ public final strictfp class Equirectangu */ @Test public void testRandomPoints() throws FactoryException, TransformException { - initialize(new Equirectangular(), true, + createCompleteProjection(new Equirectangular(), true, 0.5, // Central meridian 0, // Latitude of origin (none) 20, // Standard parallel Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -50,7 +50,7 @@ import static org.junit.Assert.*; * @version 0.6 * @module */ -@DependsOn(AbstractLambertConformalTest.class) +@DependsOn(ConformalProjectionTest.class) public final strictfp class LambertConformalTest extends MapProjectionTestCase { /** * Creates a new instance of {@link LambertConformal}. See the class javadoc for an explanation @@ -59,7 +59,7 @@ public final strictfp class LambertConfo * @param ellipse {@code false} for a sphere, or {@code true} for WGS84 ellipsoid. * @param latitudeOfOrigin The latitude of origin, in decimal degrees. */ - private void initialize(final boolean ellipse, final double latitudeOfOrigin) { + private void createNormalizedProjection(final boolean ellipse, final double latitudeOfOrigin) { final LambertConformal1SP method = new LambertConformal1SP(); final Parameters parameters = parameters(method, ellipse); parameters.getOrCreate(LambertConformal1SP.LATITUDE_OF_ORIGIN).setValue(latitudeOfOrigin); @@ -77,7 +77,7 @@ public final strictfp class LambertConfo */ @Test public void testNormalizedWKT() { - initialize(true, 40); + createNormalizedProjection(true, 40); assertWktEquals( "PARAM_MT[“Lambert_Conformal_Conic_1SP”,\n" + " PARAMETER[“semi_major”, 1.0],\n" + @@ -93,7 +93,7 @@ public final strictfp class LambertConfo @Test public void testSpecialLatitudes() throws ProjectionException { if (transform == null) { // May have been initialized by 'testSphericalCase'. - initialize(true, 40); // Elliptical case + createNormalizedProjection(true, 40); // Elliptical case } final double INF = POSITIVE_INFINITY; assertEquals ("Not a number", NaN, transform(NaN), NORMALIZED_TOLERANCE); @@ -114,7 +114,7 @@ public final strictfp class LambertConfo assertEquals ("Inverse -∞", +PI/2, inverseTransform(-INF), NORMALIZED_TOLERANCE); // Like the north case, but with sign inversed. - initialize(((LambertConformal) transform).excentricity != 0, -40); + createNormalizedProjection(((LambertConformal) transform).excentricity != 0, -40); validate(); assertEquals ("Not a number", NaN, transform(NaN), NORMALIZED_TOLERANCE); @@ -143,7 +143,7 @@ public final strictfp class LambertConfo @DependsOnMethod("testSpecialLatitudes") public void testDerivative() throws TransformException { if (transform == null) { // May have been initialized by 'testSphericalCase'. - initialize(true, 40); // Elliptical case + createNormalizedProjection(true, 40); // Elliptical case } final double delta = toRadians(100.0 / 60) / 1852; // Approximatively 100 metres. derivativeDeltas = new double[] {delta, delta}; @@ -222,7 +222,7 @@ public final strictfp class LambertConfo @Test @DependsOnMethod("testLambertConicConformal1SP") public void testLambertConicConformalWestOrientated() throws FactoryException, TransformException { - initialize(new LambertConformal1SP(), false, + createCompleteProjection(new LambertConformal1SP(), false, 0.5, // Central meridian 40, // Latitude of origin 0, // Standard parallel (none) @@ -231,7 +231,7 @@ public final strictfp class LambertConfo 100); // False northing final MathTransform reference = transform; - initialize(new LambertConformalWest(), false, + createCompleteProjection(new LambertConformalWest(), false, 0.5, // Central meridian 40, // Latitude of origin 0, // Standard parallel (none) @@ -274,25 +274,35 @@ public final strictfp class LambertConfo } /** - * Verifies the consistency of spherical formulas with the elliptical formulas. + * Performs the same tests than {@link #testSpecialLatitudes()} and {@link #testDerivative()}, + * but using spherical formulas. * * @throws FactoryException if an error occurred while creating the map projection. * @throws TransformException if an error occurred while projecting a coordinate. */ @Test - @DependsOnMethod("testSpecialLatitudes") + @DependsOnMethod({"testSpecialLatitudes", "testDerivative"}) public void testSphericalCase() throws FactoryException, TransformException { - initialize(false, 40); // Spherical case + createNormalizedProjection(false, 40); // Spherical case testSpecialLatitudes(); testDerivative(); - /* - * Make sure that the above methods did not changed the 'transform' field type. - */ + + // Make sure that the above methods did not overwrote the 'transform' field. assertEquals("transform.class", LambertConformal.Spherical.class, transform.getClass()); - /* - * For some random points, compare the result of spherical formulas with the ellipsoidal ones. - */ - initialize(new LambertConformal1SP(), false, + } + + /** + * Verifies the consistency of elliptical formulas with the spherical formulas. + * This test compares the results of elliptical formulas with the spherical ones + * for some random points. + * + * @throws FactoryException if an error occurred while creating the map projection. + * @throws TransformException if an error occurred while projecting a coordinate. + */ + @Test + @DependsOnMethod("testSphericalCase") + public void compareEllipticalWithSpherical() throws FactoryException, TransformException { + createCompleteProjection(new LambertConformal1SP(), false, 0.5, // Central meridian 40, // Latitude of origin 0, // Standard parallel (none) @@ -300,6 +310,6 @@ public final strictfp class LambertConfo 200, // False easting 100); // False northing tolerance = Formulas.LINEAR_TOLERANCE; - verifyInDomain(CoordinateDomain.GEOGRAPHIC_SAFE, 268617081); + compareEllipticalWithSpherical(CoordinateDomain.GEOGRAPHIC_SAFE, 0); } } Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -19,10 +19,12 @@ package org.apache.sis.referencing.opera import javax.measure.unit.NonSI; import org.opengis.util.FactoryException; import org.opengis.referencing.datum.Ellipsoid; +import org.opengis.referencing.operation.TransformException; import org.apache.sis.parameter.Parameters; -import org.apache.sis.internal.referencing.provider.MapProjection; import org.apache.sis.internal.util.Constants; +import org.apache.sis.internal.referencing.provider.MapProjection; import org.apache.sis.referencing.operation.DefaultOperationMethod; +import org.apache.sis.referencing.operation.transform.CoordinateDomain; import org.apache.sis.referencing.operation.transform.MathTransformTestCase; import org.apache.sis.test.mock.MathTransformFactoryMock; import org.apache.sis.test.mock.GeodeticDatumMock; @@ -79,9 +81,9 @@ strictfp class MapProjectionTestCase ext /** * Initializes a complete projection (including conversion from degrees to radians) for the given provider. * This method uses arbitrary central meridian, scale factor, false easting and false northing for increasing - * the chances to detect a mismatch. + * the chances to detect a mismatch. The result is stored in the {@link #transform} field. */ - final void initialize(final DefaultOperationMethod provider, final boolean ellipse, + final void createCompleteProjection(final DefaultOperationMethod provider, final boolean ellipse, final double centralMeridian, final double latitudeOfOrigin, final double standardParallel, @@ -147,4 +149,24 @@ strictfp class MapProjectionTestCase ext } return φ; } + + /** + * Compares the elliptical formulas with the spherical formulas for random points in the given domain. + * The spherical formulas are arbitrarily selected as the reference implementation because they are simpler, + * so less bug-prone, than the elliptical formulas. + * + * @param domain The domain of the numbers to be generated. + * @param randomSeed The seed for the random number generator, or 0 for choosing a random seed. + * @throws TransformException If a conversion, transformation or derivative failed. + */ + final void compareEllipticalWithSpherical(final CoordinateDomain domain, final long randomSeed) + throws TransformException + { + transform = ProjectionResultComparator.sphericalAndEllipsoidal(transform); + if (derivativeDeltas == null) { + final double delta = toRadians(100.0 / 60) / 1852; // Approximatively 100 metres. + derivativeDeltas = new double[] {delta, delta}; + } + verifyInDomain(domain, randomSeed); + } } Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -61,6 +61,7 @@ public final class MercatorMethodCompari /** * Where to print the outputs of this class. */ + @SuppressWarnings("UseOfSystemOutOrSystemErr") private static final PrintStream out = System.out; /** @@ -112,7 +113,7 @@ public final class MercatorMethodCompari /** * Computes φ using the series expansion given by Geomatics Guidance Note number 7, part 2. - * This is the first part of the {@link AbstractLambertConformal#φ(double)} method. + * This is the first part of the {@link ConformalProjection#φ(double)} method. * * @param t The {@code expOfSouthing} parameter value. * @return The latitude (in radians) for the given parameter. @@ -126,8 +127,32 @@ public final class MercatorMethodCompari } /** + * Same formula than {@link #bySeriesExpansion(double)}, but replacing some sine by trigonometric identities. + * The identities used are: + * + * <ul> + * <li>sin(2⋅x) = 2⋅sin(x)⋅cos(x)</li> + * <li>sin(3⋅x) = (3 - 4⋅sin²(x))⋅sin(x)</li> + * <li>sin(4⋅x) = (4 - 8⋅sin²(x))⋅sin(x)⋅cos(x)</li> + * </ul> + * + * @param t The {@code expOfSouthing} parameter value. + * @return The latitude (in radians) for the given parameter. + */ + public double usingTrigonometricIdentities(final double t) { + final double χ = PI/2 - 2*atan(t); + final double sin2χ = sin(2*χ); + final double sin_cos2χ = cos(2*χ) * sin2χ; + final double sin_sin2χ = sin2χ * sin2χ; + return c8χ * (4 - 8*sin_sin2χ)*sin_cos2χ + + c6χ * (3 - 4*sin_sin2χ)*sin2χ + + c4χ * 2*sin_cos2χ + + c2χ * sin2χ + χ; + } + + /** * Computes φ using the iterative method used by USGS. - * This is the second part of the {@link AbstractLambertConformal#φ(double)} method. + * This is the second part of the {@link ConformalProjection#φ(double)} method. * * @param t The {@code expOfSouthing} parameter value. * @return The latitude (in radians) for the given parameter. @@ -150,7 +175,7 @@ public final class MercatorMethodCompari } /** - * Basically a copy of {@link AbstractLambertConformal#expOfNorthing(double, double)}. + * Basically a copy of {@link ConformalProjection#expOfNorthing(double, double)}. */ final double expOfNorthing(final double φ) { final double ℯsinφ = excentricity * sin(φ); @@ -171,23 +196,26 @@ public final class MercatorMethodCompari /** * Implementation of {@link #printAccuracyComparison(int)} and {@link #printErrorForExcentricities(double,double)}, - * optionally with a comparison with {@link AbstractLambertConformal}. + * optionally with a comparison with {@link ConformalProjection}. */ - private void compare(final AbstractLambertConformal projection, final int numSamples, final TableAppender summarize) + private void compare(final ConformalProjection projection, final int numSamples, final TableAppender summarize) throws ProjectionException { final Statistics iterativeMethodErrors = new Statistics("Iterative method error"); final Statistics seriesExpansionErrors = new Statistics("Series expansion error"); - final Statistics abstractLambertErrors = new Statistics("'AbstractLambertConformal' error"); + final Statistics usingTrigoIdentErrors = new Statistics("Using trigonometric identities"); + final Statistics abstractLambertErrors = new Statistics("'ConformalProjection' error"); final Random random = new Random(); for (int i=0; i<numSamples; i++) { final double φ = random.nextDouble() * PI - PI/2; final double t = 1 / expOfNorthing(φ); final double byIterativeMethod = byIterativeMethod(t); final double bySeriesExpansion = bySeriesExpansion(t); + final double usingTrigoIdent = usingTrigonometricIdentities(t); iterativeMethodErrors.accept(abs(φ - byIterativeMethod) / NormalizedProjection.ITERATION_TOLERANCE); seriesExpansionErrors.accept(abs(φ - bySeriesExpansion) / NormalizedProjection.ITERATION_TOLERANCE); + usingTrigoIdentErrors.accept(abs(φ - usingTrigoIdent) / NormalizedProjection.ITERATION_TOLERANCE); if (projection != null) { abstractLambertErrors.accept(abs(φ - projection.φ(t)) / NormalizedProjection.ITERATION_TOLERANCE); } @@ -208,6 +236,7 @@ public final class MercatorMethodCompari Statistics[] stats = new Statistics[] { iterativeMethodErrors, seriesExpansionErrors, + usingTrigoIdentErrors, abstractLambertErrors }; if (projection == null) { @@ -232,7 +261,7 @@ public final class MercatorMethodCompari * Prints the error of the two methods for various excentricity values. * The intend of this method is to find an excentricity threshold value where we consider the errors too high. * - * <p>This method is used for determining empirically a value for {@link AbstractLambertConformal#EXCENTRICITY_THRESHOLD}. + * <p>This method is used for determining empirically a value for {@link ConformalProjection#EXCENTRICITY_THRESHOLD}. * The current threshold value is shown by inserting a horizontal line separator in the table when that threshold * is crossed.</p> * @@ -253,7 +282,7 @@ public final class MercatorMethodCompari final double step = 0.01; double excentricity; for (int i=0; (excentricity = min + step*i) < max; i++) { - if (!crossThreshold && excentricity >= AbstractLambertConformal.EXCENTRICITY_THRESHOLD) { + if (!crossThreshold && excentricity >= ConformalProjection.EXCENTRICITY_THRESHOLD) { crossThreshold = true; table.appendHorizontalSeparator(); } @@ -269,12 +298,47 @@ public final class MercatorMethodCompari } /** + * Compares the performance of the 3 methods. + * + * @throws ProjectionException if an error occurred in {@link #φ(double)}. + */ + private void benchmark() throws ProjectionException { + final Random random = new Random(); + final double[] t = new double[1000000]; + for (int i=0; i<t.length; i++) { + t[i] = random.nextGaussian() * 3; + } + double s0 = 0, s1 = 0, s2 = 0; + final long t0 = System.nanoTime(); + for (int i=0; i<t.length; i++) { + s0 += byIterativeMethod(t[i]); + } + final long t1 = System.nanoTime(); + for (int i=0; i<t.length; i++) { + s1 += bySeriesExpansion(t[i]); + } + final long t2 = System.nanoTime(); + for (int i=0; i<t.length; i++) { + s2 += usingTrigonometricIdentities(t[i]); + } + final long t3 = System.nanoTime(); + final float c = (t1 - t0) / 100f; + out.println("Iterative method: " + ((t1 - t0) / 1E9f) + " seconds (" + round((t1 - t0) / c) + "%)."); + out.println("Series expansion: " + ((t2 - t1) / 1E9f) + " seconds (" + round((t2 - t1) / c) + "%)."); + out.println("Trigonometric identities: " + ((t3 - t2) / 1E9f) + " seconds (" + round((t3 - t2) / c) + "%)."); + out.println("Mean φ values: " + (s0 / t.length) + ", " + + (s1 / t.length) + " and " + + (s2 / t.length) + "."); + } + + /** * The result is printed to the standard output stream. * * @param args ignored. * @throws ProjectionException if an error occurred in {@link #φ(double)}. + * @throws InterruptedException if the thread has been interrupted between two benchmarks. */ - public static void main(String[] args) throws ProjectionException { + public static void main(String[] args) throws ProjectionException, InterruptedException { out.println("Comparison of the errors of series expension and iterative method for various excentricity values."); printErrorForExcentricities(0.08, 0.3); @@ -282,24 +346,35 @@ public final class MercatorMethodCompari out.println("Comparison of the errors for a sphere."); out.println("The errors should be almost zero:"); out.println(); - AbstractLambertConformal projection = new NoOp(false); - MercatorMethodComparison alt = new MercatorMethodComparison(projection); - alt.compare(projection, 10000, null); + ConformalProjection projection = new NoOp(false); + MercatorMethodComparison c = new MercatorMethodComparison(projection); + c.compare(projection, 10000, null); out.println(); out.println("Comparison of the errors for the WGS84 excentricity."); - out.println("The 'AbstractLambertConformal' errors should be the same than the series expansion errors:"); + out.println("The 'ConformalProjection' errors should be the same than the series expansion errors:"); out.println(); projection = new NoOp(true); - alt = new MercatorMethodComparison(projection); - alt.compare(projection, 1000000, null); + c = new MercatorMethodComparison(projection); + c.compare(projection, 1000000, null); out.println(); out.println("Comparison of the errors for the excentricity of an imaginary ellipsoid."); - out.println("The 'AbstractLambertConformal' errors should be the close to the iterative method errors:"); + out.println("The 'ConformalProjection' errors should be the close to the iterative method errors:"); out.println(); projection = new NoOp(100, 95); - alt = new MercatorMethodComparison(projection); - alt.compare(projection, 1000000, null); + c = new MercatorMethodComparison(projection); + c.compare(projection, 1000000, null); + + out.println(); + out.println("Benchmarks"); + c = new MercatorMethodComparison(); + for (int i=0; i<4; i++) { + System.gc(); + Thread.sleep(1000); + c.benchmark(); + out.println(); + } + out.flush(); } } Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -31,7 +31,7 @@ import org.junit.Test; import static java.lang.Double.*; import static java.lang.StrictMath.*; import static org.opengis.test.Assert.*; -import static org.apache.sis.referencing.operation.projection.NormalizedProjectionTest.LN_INFINITY; +import static org.apache.sis.referencing.operation.projection.ConformalProjectionTest.LN_INFINITY; // Branch-specific imports import static org.junit.Assume.assumeTrue; @@ -48,14 +48,14 @@ import static org.apache.sis.test.Assert * @version 0.6 * @module */ -@DependsOn(AbstractLambertConformalTest.class) +@DependsOn(ConformalProjectionTest.class) public final strictfp class MercatorTest extends MapProjectionTestCase { /** * Creates a new instance of {@link Mercator} for a sphere or an ellipsoid. * * @param ellipse {@code false} for a sphere, or {@code true} for WGS84 ellipsoid. */ - private void initialize(final boolean ellipse) { + private void createNormalizedProjection(final boolean ellipse) { final Mercator2SP method = new Mercator2SP(); transform = new Mercator(method, parameters(method, ellipse)); if (!ellipse) { @@ -72,7 +72,7 @@ public final strictfp class MercatorTest */ @Test public void testNormalizedWKT() { - initialize(true); + createNormalizedProjection(true); assertWktEquals( "PARAM_MT[“Mercator_2SP”,\n" + " PARAMETER[“semi_major”, 1.0],\n" + @@ -87,7 +87,7 @@ public final strictfp class MercatorTest @Test public void testSpecialLatitudes() throws ProjectionException { if (transform == null) { // May have been initialized by 'testSphericalCase'. - initialize(true); // Elliptical case + createNormalizedProjection(true); // Elliptical case } assertEquals ("Not a number", NaN, transform(NaN), tolerance); assertEquals ("Out of range", NaN, transform(+2), tolerance); @@ -118,11 +118,11 @@ public final strictfp class MercatorTest @DependsOnMethod("testSpecialLatitudes") public void testDerivative() throws TransformException { if (transform == null) { // May have been initialized by 'testSphericalCase'. - initialize(true); // Elliptical case + createNormalizedProjection(true); // Elliptical case } - final double delta = toRadians(100.0 / 60) / 1852; // Approximatively 100 metres. + final double delta = toRadians(100.0 / 60) / 1852; // Approximatively 100 metres. derivativeDeltas = new double[] {delta, delta}; - tolerance = 1E-9; + tolerance = 1E-9; // More severe than Formulas.LINEAR_TOLERANCE. verifyDerivative(toRadians(15), toRadians( 30)); verifyDerivative(toRadians(10), toRadians(-60)); } @@ -218,25 +218,35 @@ public final strictfp class MercatorTest } /** - * Verifies the consistency of spherical formulas with the elliptical formulas. + * Performs the same tests than {@link #testSpecialLatitudes()} and {@link #testDerivative()}, + * but using spherical formulas. * * @throws FactoryException if an error occurred while creating the map projection. * @throws TransformException if an error occurred while projecting a coordinate. */ @Test - @DependsOnMethod("testSpecialLatitudes") + @DependsOnMethod({"testSpecialLatitudes", "testDerivative"}) public void testSphericalCase() throws FactoryException, TransformException { - initialize(false); // Spherical case + createNormalizedProjection(false); // Spherical case testSpecialLatitudes(); testDerivative(); - /* - * Make sure that the above methods did not overwrote the 'transform' field. - */ + + // Make sure that the above methods did not overwrote the 'transform' field. assertEquals("transform.class", Mercator.Spherical.class, transform.getClass()); - /* - * For some random points, compare the result of spherical formulas with the ellipsoidal ones. - */ - initialize(new Mercator1SP(), false, + } + + /** + * Verifies the consistency of elliptical formulas with the spherical formulas. + * This test compares the results of elliptical formulas with the spherical ones + * for some random points. + * + * @throws FactoryException if an error occurred while creating the map projection. + * @throws TransformException if an error occurred while projecting a coordinate. + */ + @Test + @DependsOnMethod("testSphericalCase") + public void compareEllipticalWithSpherical() throws FactoryException, TransformException { + createCompleteProjection(new Mercator1SP(), false, 0.5, // Central meridian 0, // Latitude of origin (none) 0, // Standard parallel (none) @@ -244,6 +254,6 @@ public final strictfp class MercatorTest 200, // False easting 100); // False northing tolerance = Formulas.LINEAR_TOLERANCE; - verifyInDomain(CoordinateDomain.GEOGRAPHIC_SAFE, 84018710); + compareEllipticalWithSpherical(CoordinateDomain.GEOGRAPHIC_SAFE, 0); } } Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -39,7 +39,7 @@ import org.apache.sis.util.Workaround; * @module */ @SuppressWarnings("serial") -final strictfp class NoOp extends AbstractLambertConformal { +final strictfp class NoOp extends ConformalProjection { /** * Creates a new "no-operation". * Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -16,23 +16,14 @@ */ package org.apache.sis.referencing.operation.projection; -import org.opengis.referencing.operation.TransformException; -import org.apache.sis.referencing.operation.transform.AbstractMathTransform1D; import org.apache.sis.referencing.operation.transform.TransformTestCase; -import org.apache.sis.internal.util.DoubleDouble; -import org.apache.sis.test.DependsOnMethod; import org.apache.sis.test.DependsOn; -import org.apache.sis.test.TestUtilities; import org.junit.Test; -import static java.lang.Double.*; import static java.lang.StrictMath.*; import static org.apache.sis.internal.metadata.ReferencingServices.NAUTICAL_MILE; import static org.junit.Assert.*; -// Branch-dependent imports -import static org.apache.sis.internal.jdk8.JDK8.nextDown; - /** * Tests the {@link NormalizedProjection} class. @@ -44,7 +35,7 @@ import static org.apache.sis.internal.jd */ @DependsOn({ // Following dependency is where the basic parameters (e.g. SEMI_MAJOR) are tested. - // Those parameters are needed by NoOp pseudo-projection, which is used in this class. + // Those parameters are needed by NoOp pseudo-projection, which is used in this package. org.apache.sis.internal.referencing.provider.MapProjectionTest.class }) public final strictfp class NormalizedProjectionTest extends TransformTestCase { @@ -54,34 +45,6 @@ public final strictfp class NormalizedPr static final double TOLERANCE = 1E-12; /** - * Natural logarithm of the pseudo-infinity as returned by Mercator formulas in the spherical - * case, truncated to nearest integer. This is not a real infinity because there is no exact - * representation of π/2 in base 2, so tan(π/2) is not positive infinity. - */ - static final int LN_INFINITY = 37; - - /** - * Computes {@link NormalizedProjection#expOfNorthing(double, double)} for the given latitude. - * - * @param projection The projection on which to invoke {@code expOfNorthing(…)}. - * @param φ The latitude in radians. - * @return {@code Math.exp} of the Mercator projection of the given latitude. - */ - static double expOfNorthing(final NormalizedProjection projection, final double φ) { - return projection.expOfNorthing(φ, projection.excentricity * sin(φ)); - } - - /** - * Computes {@link NormalizedProjection#expOfNorthing(double, double)} for the given latitude. - * - * @param φ The latitude in radians. - * @return {@code Math.exp} of the Mercator projection of the given latitude. - */ - private double expOfNorthing(final double φ) { - return expOfNorthing((NormalizedProjection) transform, φ); - } - - /** * Tests the value documented in the javadoc. Those value may be freely changed; * those tests exist only to increase the chances that the documented values are right. */ @@ -106,148 +69,4 @@ public final strictfp class NormalizedPr transform = projection = new NoOp(true); assertEquals("excentricity", 0.08181919084262157, projection.excentricity, TOLERANCE); } - - /** - * Tests a few formulas used by the Mercator projection in the spherical case. - * This is a little bit more a Java test than an Apache SIS test (or to be more - * accurate, a test of our understanding of the {@code java.lang.Math} library). - * - * {@preformat text - * Forward: y = log(tan(π/4 + φ/2)) - * Inverse: φ = π/2 - 2*atan(exp(-y)) - * } - */ - @Test - public void testMath() { - assertEquals("Forward 0°N", 0, log(tan(PI/4)), TOLERANCE); - assertEquals("Inverse 0 m", 0, PI/2 - 2*atan(exp(0)), TOLERANCE); - assertEquals("Forward 90°S", NEGATIVE_INFINITY, log(tan(0)), TOLERANCE); - assertEquals("Forward (90+ε)°S", NaN, log(tan(-nextUp(0))), TOLERANCE); - assertEquals("Inverse -∞", PI/2, atan(exp(-NEGATIVE_INFINITY)), TOLERANCE); - assertEquals("Inverse -∞ appr.", PI/2, atan(exp(LN_INFINITY + 1)), TOLERANCE); - /* - * tan(PI/2) do not produces positive infinity as we would expect, because there is no - * exact representation of PI in base 2. Experiments show that we get some high value - * instead (1.633E+16 on my machine, having a logarithm of 37.332). - */ - assertTrue ("Forward 90°N", 1E+16 < tan(PI/2)); - assertTrue ("Forward 90°N", LN_INFINITY < log(tan(PI/2))); - assertEquals("Forward (90+ε)°N", NaN, log(tan(nextUp(PI/2))), TOLERANCE); - assertEquals("Inverse +∞", 0, atan(exp(NEGATIVE_INFINITY)), TOLERANCE); - assertEquals("Inverse +∞ appr.", 0, atan(exp(-(LN_INFINITY + 1))), TOLERANCE); - /* - * Some checks performed in our projection implementations assume that - * conversion of 90° to radians give exactly Math.PI/2. - */ - final DoubleDouble dd = DoubleDouble.createDegreesToRadians(); - dd.multiply(90); - assertEquals(PI/2, dd.value, 0.0); - assertEquals(PI/2, toRadians(90), 0.0); - } - - /** - * Tests the {@link NormalizedProjection#expOfNorthing(double, double)} function. - * - * {@preformat text - * Forward: y = -log(t(φ)) - * Inverse: φ = φ(exp(-y)) - * } - */ - @Test - public void testExpOfNorthing() { - transform = new NoOp(false); // Spherical case - tolerance = TOLERANCE; - doTestExpOfNorthing(); - transform = new NoOp(true); // Ellipsoidal case - doTestExpOfNorthing(); - } - - /** - * Implementation of {@link #testExpOfNorthing()}. - * The {@link #projection} field must have been set before this method is called. - */ - private void doTestExpOfNorthing() { - assertEquals("f(NaN) = NaN", NaN, expOfNorthing(NaN), tolerance); - assertEquals("f( ±∞) = NaN", NaN, expOfNorthing(NEGATIVE_INFINITY), tolerance); - assertEquals("f( ±∞) = NaN", NaN, expOfNorthing(POSITIVE_INFINITY), tolerance); - assertEquals("f( 0°) = 1", 1, expOfNorthing(0), tolerance); - assertEquals("f(-90°) = 0", 0, expOfNorthing(-PI/2), tolerance); - assertTrue ("f(< -90°) < 0", expOfNorthing(-PI/2 - 0.1) < 0); - assertTrue ("f(< -90°) < 0", expOfNorthing(nextDown(-PI/2)) < 0); - /* - * Values around π/2 are a special case. Theoretically the result should be positive infinity. - * But since we do not have an exact representatation of π/2, we instead get a high number. - * Furthermore the value does not become negative immediately after π/2; we have to skip an - * other IEEE 754 double value. This is because the real π/2 value is actually between PI/2 - * and nextUp(PI/2): - * - * PI/2 = 1.570796326794896558… - * π/2 = 1.570796326794896619… - * nextUp(PI/2) = 1.570796326794896780… - */ - assertTrue("f(+90°) → ∞", expOfNorthing(+PI/2) > exp(LN_INFINITY)); - assertTrue("f(> +90°) < 0", expOfNorthing(+PI/2 + 0.1) < 0); - assertTrue("f(> +90°) < 0", expOfNorthing(nextUp(nextUp(+PI/2))) < 0); - /* - * Test function periodicity. This is not a strong requirement for the expOfNorthing(…) function, - * but we nevertheless try to ensure that the method behaves correctly with unexpected values. - */ - assertEquals("f(+360°)", 1, expOfNorthing(+2*PI), tolerance); - assertEquals("f(+270°)", 0, expOfNorthing(+PI*3/2), tolerance); - assertEquals("f(+180°)", -1, expOfNorthing(+PI), tolerance); - assertEquals("f(-180°)", -1, expOfNorthing(-PI), tolerance); - assertTrue ("f(-270°) → ∞", expOfNorthing(-PI*3/2) < exp(-LN_INFINITY)); - assertEquals("f(-360°)", 1, expOfNorthing(-2*PI), tolerance); - assertEquals("f(-450°)", 0, expOfNorthing(-PI*5/2), tolerance); - /* - * Use in a way close to (but not identical) - * to the way the Mercator projection need it. - */ - assertEquals("Mercator(0°)", 0, log(expOfNorthing(0)), tolerance); - assertEquals("Mercator(90°S)", NEGATIVE_INFINITY, log(expOfNorthing(-PI/2)), tolerance); - assertTrue ("Mercator(90°N)", LN_INFINITY < log(expOfNorthing(+PI/2))); - } - - /** - * Tests the {@link NormalizedProjection#dy_dφ(double, double)} method. - * - * @throws TransformException Should never happen. - */ - @Test - @DependsOnMethod("testExpOfNorthing") - public void test_dy_dφ() throws TransformException { - tolerance = 1E-7; - doTest_dy_dφ(new NoOp(false)); // Spherical case - doTest_dy_dφ(new NoOp(true)); // Ellipsoidal case - } - - /** - * Implementation of {@link #test_dy_dφ()}. - * The {@link #projection} field must have been set before this method is called. - */ - private void doTest_dy_dφ(final NoOp projection) throws TransformException { - transform = new AbstractMathTransform1D() { - @Override public double transform(final double φ) { - return expOfNorthing(projection, φ); - } - @Override public double derivative(final double φ) { - final double sinφ = sin(φ); - return projection.dy_dφ(sinφ, cos(φ)) * expOfNorthing(projection, φ); - } - }; - verifyInDomain(-89 * (PI/180), 89 * (PI/180)); // Verify from 85°S to 85°N. - } - - /** - * Convenience method invoking {@link TransformTestCase#verifyInDomain} for an 1D transform. - */ - private void verifyInDomain(final double min, final double max) throws TransformException { - derivativeDeltas = new double[] {2E-8}; - isInverseTransformSupported = false; - verifyInDomain( - new double[] {min}, // Minimal value to test. - new double[] {max}, // Maximal value to test. - new int[] {100}, // Number of points to test. - TestUtilities.createRandomNumberGenerator()); - } } Copied: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/PolarStereographicTest.java (from r1692168, sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/PolarStereographicTest.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/PolarStereographicTest.java?p2=sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/PolarStereographicTest.java&p1=sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/PolarStereographicTest.java&r1=1692168&r2=1692172&rev=1692172&view=diff ============================================================================== --- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/PolarStereographicTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/PolarStereographicTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -127,7 +127,7 @@ public final strictfp class PolarStereog */ @Test public void testPolarStereographicA() throws FactoryException, TransformException { - createGeoApiTest(new PolarStereographicA()).testPolarStereographicA(); + new PolarStereographicA(); // Test creation only, as GeoAPI 3.0 did not yet had the test method. } /** @@ -141,7 +141,7 @@ public final strictfp class PolarStereog */ @Test public void testPolarStereographicB() throws FactoryException, TransformException { - createGeoApiTest(new PolarStereographicB()).testPolarStereographicB(); + new PolarStereographicB(); // Test creation only, as GeoAPI 3.0 did not yet had the test method. } /** @@ -155,7 +155,7 @@ public final strictfp class PolarStereog */ @Test public void testPolarStereographicC() throws FactoryException, TransformException { - createGeoApiTest(new PolarStereographicC()).testPolarStereographicC(); + new PolarStereographicC(); // Test creation only, as GeoAPI 3.0 did not yet had the test method. } /** Copied: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java (from r1692168, sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java?p2=sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java&p1=sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java&r1=1692168&r2=1692172&rev=1692172&view=diff ============================================================================== --- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -63,7 +63,7 @@ public final strictfp class TransverseMe @Test @org.junit.Ignore("Missing implementation of the projection derivative.") public void testTransverseMercator() throws FactoryException, TransformException { - createGeoApiTest(new org.apache.sis.internal.referencing.provider.TransverseMercator()).testTransverseMercator(); + new org.apache.sis.internal.referencing.provider.TransverseMercator(); // Test creation only, as GeoAPI 3.0 did not yet had the test method. } /** @@ -78,7 +78,7 @@ public final strictfp class TransverseMe @Test @org.junit.Ignore("Missing implementation of the projection derivative.") public void testTransverseMercatorSouthOrientated() throws FactoryException, TransformException { - createGeoApiTest(new TransverseMercatorSouth()).testTransverseMercatorSouthOrientated(); + new TransverseMercatorSouth(); // Test creation only, as GeoAPI 3.0 did not yet had the test method. } /** Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -19,6 +19,7 @@ package org.apache.sis.referencing.opera import java.util.Random; import org.apache.sis.measure.Latitude; import org.apache.sis.measure.Longitude; + import static java.lang.StrictMath.*; import static org.apache.sis.internal.metadata.ReferencingServices.AUTHALIC_RADIUS; @@ -100,7 +101,7 @@ public strictfp class CoordinateDomain { public static final CoordinateDomain GEOGRAPHIC_POLES = new CoordinateDomain( Longitude.MIN_VALUE, Longitude.MAX_VALUE, Latitude .MIN_VALUE, Latitude .MAX_VALUE, - -0*5 * HEIGHT, 0.5 * HEIGHT) + -HEIGHT, HEIGHT) { @Override public double[] generateRandomInput(final Random random, final int dimension, final int numPts) { @@ -119,6 +120,24 @@ public strictfp class CoordinateDomain { }; /** + * Geographic input coordinates close to the north pole. + * Ordinates are in (<var>longitude</var>, <var>latitude</var>, <var>height</var>) order. + */ + public static final CoordinateDomain GEOGRAPHIC_NORTH_POLE = new CoordinateDomain( + Longitude.MIN_VALUE, Longitude.MAX_VALUE, + ARTICLE_CIRCLE, Latitude .MAX_VALUE, + -HEIGHT, HEIGHT); + + /** + * Geographic input coordinates close to the south pole. + * Ordinates are in (<var>longitude</var>, <var>latitude</var>, <var>height</var>) order. + */ + public static final CoordinateDomain GEOGRAPHIC_SOUTH_POLE = new CoordinateDomain( + Longitude.MIN_VALUE, Longitude.MAX_VALUE, + Latitude .MIN_VALUE, -ARTICLE_CIRCLE, + -HEIGHT, HEIGHT); + + /** * Geographic input coordinates with angles in radians. * Ordinates are in (<var>lambda</var>, <var>phi</var>, <var>height</var>) order. */ Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomainTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomainTest.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomainTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomainTest.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -107,15 +107,45 @@ public class CoordinateDomainTest extend public void testGeographicPole() { assertArrayEquals(new double[] { // ……λ …………φ ………………H - -136.6, -74.3, 2467.5, - -17.9, 74.7, 2338.4, - 98.2, 66.9, 2078.0, - 151.9, 73.8, 2799.3, - -90.5, -86.4, 585.3 + -136.6, -74.3, -130.1, + -17.9, 74.7, -646.5, + 98.2, 66.9, -1687.9, + 151.9, 73.8, 1197.0, + -90.5, -86.4, -7658.8 }, CoordinateDomain.GEOGRAPHIC_POLES.generateRandomInput(new Random(6784869539382621964L), 3, 5), TOLERANCE); } /** + * Tests {@link CoordinateDomain#GEOGRAPHIC_NORTH_POLE}. + */ + @Test + public void testGeographicNorthPole() { + assertArrayEquals(new double[] { + // ……λ …………φ ………………H + -41.7, 72.6, 9605.3, + -107.7, 68.2, 388.5, + 32.9, 69.3, 2553.6, + 106.5, 81.0, -7334.3, + 135.2, 87.6, -3518.9 + }, CoordinateDomain.GEOGRAPHIC_NORTH_POLE.generateRandomInput(new Random(2141713460614422218L), 3, 5), TOLERANCE); + } + + /** + * Tests {@link CoordinateDomain#GEOGRAPHIC_SOUTH_POLE}. + */ + @Test + public void testGeographicSouthPole() { + assertArrayEquals(new double[] { + // ……λ …………φ ………………H + -106.2, -71.9, -2202.6, + -172.6, -89.5, 2428.1, + 33.2, -84.3, 6068.1, + -64.3, -76.3, -3436.7, + -97.6, -72.5, 8702.2 + }, CoordinateDomain.GEOGRAPHIC_SOUTH_POLE.generateRandomInput(new Random(5769644852151897296L), 3, 5), TOLERANCE); + } + + /** * Tests {@link CoordinateDomain#GEOGRAPHIC_RADIANS}. */ @Test Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -101,9 +101,11 @@ import org.junit.BeforeClass; // Test map projections. Those tests need the providers tested above. org.apache.sis.referencing.operation.projection.NormalizedProjectionTest.class, org.apache.sis.referencing.operation.projection.EquirectangularTest.class, - org.apache.sis.referencing.operation.projection.AbstractLambertConformalTest.class, + org.apache.sis.referencing.operation.projection.ConformalProjectionTest.class, org.apache.sis.referencing.operation.projection.MercatorTest.class, org.apache.sis.referencing.operation.projection.LambertConformalTest.class, + org.apache.sis.referencing.operation.projection.TransverseMercatorTest.class, + org.apache.sis.referencing.operation.projection.PolarStereographicTest.class, // Coordinate Reference System components. org.apache.sis.referencing.datum.BursaWolfParametersTest.class, Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java?rev=1692172&r1=1692171&r2=1692172&view=diff ============================================================================== --- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java [UTF-8] (original) +++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java [UTF-8] Tue Jul 21 16:57:38 2015 @@ -83,6 +83,7 @@ abstract class StringConverter<T> extend * @param targetClass The {@linkplain #getTargetClass() target class}. * @param inverse The inverse converter from the target to the source class. */ + @SuppressWarnings("OverridableMethodCallDuringObjectConstruction") StringConverter(final Class<T> targetClass) { super(String.class, targetClass); inverse = createInverse();
