You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2015/04/07 22:28:43 UTC
svn commit: r1671939 - in /sis/branches/JDK8/core:
sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/
sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/
sis-referencing/src/main/java/org/apache/sis/referenci...
Author: desruisseaux
Date: Tue Apr 7 20:28:42 2015
New Revision: 1671939
URL: http://svn.apache.org/r1671939
Log:
Referencing: complete the implementation of Equirectangular projection (actually implemented by an affine transform).
As a side effect, tuned again the way we manage parameters, especially the calculation of radius of conformal sphere.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -21,7 +21,6 @@ import java.awt.geom.AffineTransform;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.referencing.operation.MathTransform;
-import org.apache.sis.parameter.Parameterized;
/**
@@ -54,9 +53,9 @@ public final class ParameterizedAffine e
private static final long serialVersionUID = 906346920928432466L;
/**
- * An object capable to provide the parameters used for creating this transform.
+ * The (presumed immutable) parameters used for creating this transform.
*/
- public final Parameterized parameters;
+ private final ParameterValueGroup parameters;
/**
* {@code true} if {@link #parameters} provides an accurate description of this transform, or
@@ -70,11 +69,11 @@ public final class ParameterizedAffine e
* Creates a new transform from the given affine and parameters.
*
* @param transform The affine transform to copy.
- * @param parameters The parameters to remember.
+ * @param parameters The parameters to remember. It is caller's responsibility to provide an immutable instance.
* @param isDefinitive {@code true} if {@code parameters} provides an accurate description of {@code transform}, or
* {@code false} if the transform may be different than the one described by {@code parameters}.
*/
- public ParameterizedAffine(final AffineTransform transform, final Parameterized parameters, final boolean isDefinitive) {
+ public ParameterizedAffine(final AffineTransform transform, final ParameterValueGroup parameters, final boolean isDefinitive) {
super(transform);
this.parameters = parameters;
this.isDefinitive = isDefinitive;
@@ -104,7 +103,7 @@ public final class ParameterizedAffine e
*/
@Override
public ParameterDescriptorGroup getParameterDescriptors() {
- return isDefinitive ? parameters.getParameterDescriptors() : super.getParameterDescriptors();
+ return isDefinitive ? parameters.getDescriptor() : super.getParameterDescriptors();
}
/**
@@ -115,7 +114,7 @@ public final class ParameterizedAffine e
*/
@Override
public ParameterValueGroup getParameterValues() {
- return isDefinitive ? parameters.getParameterValues() : super.getParameterValues();
+ return isDefinitive ? parameters : super.getParameterValues();
}
/**
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -16,22 +16,34 @@
*/
package org.apache.sis.internal.referencing.provider;
+import java.awt.geom.AffineTransform;
+import org.opengis.util.FactoryException;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.operation.CylindricalProjection;
-
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransformFactory;
+import org.apache.sis.parameter.Parameters;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransforms;
+import org.apache.sis.internal.referencing.j2d.ParameterizedAffine;
+import org.apache.sis.internal.util.Constants;
import org.apache.sis.util.resources.Messages;
+import static java.lang.Math.*;
+
/**
* The provider for "<cite>Equidistant Cylindrical (Spherical)</cite>" projection
* (EPSG:1029, <span class="deprecated">EPSG:9823</span>).
*
+ * At the difference of most other map projection providers, this class does not extend {@link MapProjection}
+ * because it does not create non-liner kernel. Instead, the projection created by this class is implemented
+ * by an affine transform.
+ *
* <div class="note"><b>Note:</b>
* EPSG defines two codes for this projection, 1029 being the spherical case and 1028 the ellipsoidal case.
* However the formulas are the same in both cases, with an additional adjustment of Earth radius in the
@@ -104,7 +116,7 @@ public final class Equirectangular exten
STANDARD_PARALLEL = createLatitude(builder
.addIdentifier("8823")
.addName("Latitude of 1st standard parallel")
- .addName(Citations.OGC, "standard_parallel_1")
+ .addName(Citations.OGC, Constants.STANDARD_PARALLEL_1)
.addName(Citations.ESRI, "Standard_Parallel_1")
.addName(Citations.NETCDF, "standard_parallel")
.addName(Citations.GEOTIFF, "ProjStdParallel1")
@@ -113,7 +125,7 @@ public final class Equirectangular exten
CENTRAL_MERIDIAN = createLongitude(builder
.addIdentifier("8802")
.addName("Longitude of natural origin")
- .addName(Citations.OGC, "central_meridian")
+ .addName(Citations.OGC, Constants.CENTRAL_MERIDIAN)
.addName(Citations.ESRI, "Central_Meridian")
.addName(Citations.NETCDF, "longitude_of_projection_origin")
.addName(Citations.GEOTIFF, "ProjCenterLong")
@@ -122,7 +134,7 @@ public final class Equirectangular exten
FALSE_EASTING = createShift(builder
.addIdentifier("8806")
.addName("False easting")
- .addName(Citations.OGC, "false_easting")
+ .addName(Citations.OGC, Constants.FALSE_EASTING)
.addName(Citations.ESRI, "False_Easting")
.addName(Citations.NETCDF, "false_easting")
.addName(Citations.GEOTIFF, "FalseEasting")
@@ -131,7 +143,7 @@ public final class Equirectangular exten
FALSE_NORTHING = createShift(builder
.addIdentifier("8807")
.addName("False northing")
- .addName(Citations.OGC, "false_northing")
+ .addName(Citations.OGC, Constants.FALSE_NORTHING)
.addName(Citations.ESRI, "False_Northing")
.addName(Citations.NETCDF, "false_northing")
.addName(Citations.GEOTIFF, "FalseNorthing")
@@ -165,7 +177,7 @@ public final class Equirectangular exten
.addIdentifier(Citations.GEOTIFF, "17")
.createGroupForMapProjection(
STANDARD_PARALLEL,
- LATITUDE_OF_ORIGIN,
+ LATITUDE_OF_ORIGIN, // Not formally an Equirectangular parameter.
CENTRAL_MERIDIAN,
FALSE_EASTING,
FALSE_NORTHING);
@@ -189,12 +201,70 @@ public final class Equirectangular exten
}
/**
- * {@inheritDoc}
+ * Creates an Equirectangular projection from the specified group of parameter values.
*
+ * @param factory The factory to use if this constructor needs to create other math transforms.
+ * @param parameters The parameter values that define the transform to create.
* @return The map projection created from the given parameter values.
+ * @throws FactoryException if an error occurred while creating the math transform.
*/
@Override
- public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup parameters) {
- return null;
+ public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup parameters)
+ throws FactoryException
+ {
+ return createMathTransform(this, factory, Parameters.castOrWrap(parameters));
+ }
+
+ /**
+ * Creates an Equirectangular or Plate-Carrée projection from the specified group of parameter values. This
+ * method is an adaptation of {@link org.apache.sis.referencing.operation.projection.NormalizedProjection}
+ * constructor, reproduced in this method because we will create an affine transform instead than the usual
+ * projection classes.
+ */
+ static MathTransform createMathTransform(final AbstractProvider method, final MathTransformFactory factory,
+ final Parameters parameters) throws FactoryException
+ {
+ final ContextualParameters context = new ContextualParameters(method);
+ double a = MapProjection.getAndStore(parameters, context, MapProjection.SEMI_MAJOR);
+ double b = MapProjection.getAndStore(parameters, context, MapProjection.SEMI_MINOR);
+ double λ0 = MapProjection.getAndStore(parameters, context, CENTRAL_MERIDIAN);
+ double φ0 = MapProjection.getAndStore(parameters, context, LATITUDE_OF_ORIGIN);
+ double φ1 = MapProjection.getAndStore(parameters, context, STANDARD_PARALLEL);
+ double fe = MapProjection.getAndStore(parameters, context, FALSE_EASTING);
+ double fn = MapProjection.getAndStore(parameters, context, FALSE_NORTHING);
+ /*
+ * Perform following transformation, in that order. Note that following
+ * AffineTransform convention, the Java code appears in reverse order:
+ *
+ * 1) Subtract φ0 to the latitude.
+ * 2) Subtract λ0 to the longitude.
+ * 3) Convert degrees to radians.
+ * 4) Scale longitude by cos(φ1).
+ */
+ φ1 = toRadians(φ1);
+ context.getMatrix(true).concatenate(0, cos(φ1), null);
+ context.normalizeGeographicInputs(λ0)
+ .concatenate(1, null, -φ0);
+ /*
+ * At this point, we usually invoke scaleAndTranslate2D(false, a, fe, fn) where 'a' (the semi-major
+ * axis length) is taken as the Earth radius (R). However quoting EPSG: "If the figure of the earth
+ * used is an ellipsoid rather than a sphere then R should be calculated as the radius of the conformal
+ * sphere at the projection origin at latitude φ1 using the formula for RC given in section 1.2, table 3".
+ */
+ if (a != b) {
+ final double rs = b / a;
+ final double sinφ1 = sin(φ1);
+ a = b / (1 - (1 - rs*rs) * (sinφ1*sinφ1));
+ }
+ context.scaleAndTranslate2D(false, a, fe, fn);
+ /*
+ * Creates the ConcatenatedTransform, letting the factory returns the cached instance
+ * if the caller already invoked this method previously (which usually do not happen).
+ */
+ MathTransform mt = context.completeTransform(factory, MathTransforms.identity(2));
+ if (mt instanceof AffineTransform) { // Always true in Apache SIS implementation.
+ mt = new ParameterizedAffine((AffineTransform) mt, context, true);
+ }
+ return mt;
}
}
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -41,10 +41,14 @@ import org.apache.sis.metadata.iso.citat
import org.apache.sis.parameter.DefaultParameterDescriptor;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.parameter.Parameters;
+import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Messages;
import static org.opengis.metadata.Identifier.AUTHORITY_KEY;
+// Branch-dependent imports
+import java.util.Objects;
+
/**
* Base class for all map projection providers defined in this package. This base class defines some descriptors
@@ -123,6 +127,57 @@ public abstract class MapProjection exte
}
/**
+ * Gets a parameter value identified by the given descriptor and stores it in the {@code context}.
+ * This method performs the following actions:
+ *
+ * <ul>
+ * <li>Convert the value to the units specified by the descriptor.</li>
+ * <li>Ensure that the value is contained in the range specified by the descriptor.</li>
+ * <li>Store the value only if different than the default value.</li>
+ * </ul>
+ *
+ * This method should be invoked at {@link #createMathTransform(MathTransformFactory, ParameterValueGroup)}
+ * execution time only.
+ *
+ * @param source The parameters from which to read the value.
+ * @param target Where to store the parameter values.
+ * @param descriptor The descriptor that specify the parameter names and desired units.
+ * @return The parameter value in the units given by the descriptor.
+ * @throws IllegalArgumentException if the given value is out of bounds.
+ */
+ public static double getAndStore(final Parameters source, final ParameterValueGroup target,
+ final ParameterDescriptor<Double> descriptor) throws IllegalArgumentException
+ {
+ final double value = source.doubleValue(descriptor); // Apply a unit conversion if needed.
+ if (Double.isNaN(value) || Double.isInfinite(value)) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalParameterValue_2,
+ descriptor.getName(), value));
+ }
+ final Comparable<Double> min = descriptor.getMinimumValue();
+ final Comparable<Double> max = descriptor.getMaximumValue();
+ if (!Objects.equals(min, max)) {
+ /*
+ * RATIONAL: why we do not check the bounds if (min == max):
+ * The only case when our descriptor have (min == max) is when a parameter can only be zero,
+ * because of the way the map projection is defined (see e.g. Mercator1SP.LATITUDE_OF_ORIGIN).
+ * But in some cases, it would be possible to deal with non-zero values, even if in principle
+ * we should not. In such case we let the caller decides.
+ */
+ if ((min instanceof Number && !(value >= ((Number) min).doubleValue())) ||
+ (max instanceof Number && !(value <= ((Number) max).doubleValue())))
+ {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.ValueOutOfRange_4,
+ descriptor.getName(), min, max, value));
+ }
+ }
+ final Double defaultValue = descriptor.getDefaultValue();
+ if (defaultValue == null || !defaultValue.equals(value)) {
+ target.parameter(descriptor.getName().getCode()).setValue(value);
+ }
+ return value;
+ }
+
+ /**
* Creates a map projection from the specified group of parameter values.
*
* @param factory The factory to use for creating and concatenating the (de)normalization transforms.
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -18,6 +18,7 @@ package org.apache.sis.internal.referenc
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
+import org.apache.sis.internal.util.Constants;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.metadata.iso.citation.Citations;
@@ -80,7 +81,7 @@ public final class Mercator1SP extends A
SCALE_FACTOR = createScale(builder
.addIdentifier("8805")
.addName("Scale factor at natural origin")
- .addName(Citations.OGC, "scale_factor")
+ .addName(Citations.OGC, Constants.SCALE_FACTOR)
.addName(Citations.ESRI, "Scale_Factor")
.addName(Citations.NETCDF, "scale_factor_at_projection_origin")
.addName(Citations.GEOTIFF, "ScaleAtNatOrigin")
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -55,7 +55,7 @@ public final class MercatorSpherical ext
static {
final ParameterBuilder builder = builder();
/*
- * The "Scale factor at natural origin" is not formally a parameter for this map projection.
+ * The "Latitude of 1st standard parallel" is not formally a parameter for this map projection.
* But we declare it (as an optional parameter) for compatibility with those who still use it.
*/
final ParameterDescriptor<?> standardParallel = createLatitude(builder
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -133,15 +133,16 @@ public class Mercator extends Normalized
@Workaround(library="JDK", version="1.7")
private Mercator(final OperationMethod method, final Parameters parameters, final byte type) {
super(method, parameters,
- (type == REGIONAL) ? RegionalMercator .EASTING_AT_FALSE_ORIGIN : AbstractMercator.FALSE_EASTING,
- (type == REGIONAL) ? RegionalMercator.NORTHING_AT_FALSE_ORIGIN : AbstractMercator.FALSE_NORTHING);
+ (type == SPHERICAL) ? Mercator2SP .STANDARD_PARALLEL : null,
+ (type == REGIONAL ) ? RegionalMercator.EASTING_AT_FALSE_ORIGIN : AbstractMercator.FALSE_EASTING,
+ (type == REGIONAL ) ? RegionalMercator.NORTHING_AT_FALSE_ORIGIN : AbstractMercator.FALSE_NORTHING);
this.type = type;
/*
* 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.
*/
- double λ0 = getAndStore(parameters, Mercator1SP.CENTRAL_MERIDIAN);
+ final double λ0 = getAndStore(parameters, Mercator1SP.CENTRAL_MERIDIAN);
/*
* 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)
@@ -154,30 +155,17 @@ public class Mercator extends Normalized
* "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".
*/
- double φ0 = toRadians(getAndStore(parameters, (type == REGIONAL)
+ final double φ0 = toRadians(getAndStore(parameters, (type == 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
* are mutually exclusive. The former is for projections of category "2SP" (namely variant B and C) while
- * the later is for projections "1SP" (namely variant A and spherical).
+ * the later is for projections "1SP" (namely variant A and spherical). However we let users specify both
+ * if they really want, since we sometime see such CRS definitions.
*/
- double φ1 = toRadians(getAndStore(parameters, Mercator2SP.STANDARD_PARALLEL));
+ final double φ1 = toRadians(getAndStore(parameters, Mercator2SP.STANDARD_PARALLEL));
double k0 = getAndStore(parameters, Mercator1SP.SCALE_FACTOR);
- /*
- * A correction that allows us to employ a standard parallel that is not correspondent to the equator,
- * as described in Snyder and al. at page 47. This is the same correction factor than the one applied
- * for the Mercator (2SP) case, constant "ko" in EPSG:9805.
- *
- * The scale correction is multiplied with the global scale, which allows the Apache SIS referencing
- * module to merge this correction with the scale factor in a single multiplication. In principle we
- * should never have both the scale factor and a standard parallel. Nevertheless we sometime see such
- * CRS definitions.
- */
- switch (type) {
- case PSEUDO: /* Do nothing since a is taken as the radius. */ break;
- case SPHERICAL: k0 *= radiusOfConformalSphere(sin(φ1)); break;
- default: k0 *= cos(φ1) / rν(sin(φ1)); break;
- }
+ k0 *= cos(φ1) / rν(sin(φ1));
/*
* In principle we should rotate the central meridian (λ0) in the normalization transform, as below:
*
@@ -231,8 +219,7 @@ public class Mercator extends Normalized
* coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates in <em>metres</em>.
*
* <p>The non-linear part of the returned transform will be {@code this} transform, except if the ellipsoid
- * {@linkplain #isSpherical() is spherical}. In the later case, {@code this} transform will be replaced by
- * a simplified implementation.</p>
+ * is spherical. In the later case, {@code this} transform will be replaced by a simplified implementation.</p>
*
* @param factory The factory to use for creating the transform.
* @return The map projection from (λ,φ) to (<var>x</var>,<var>y</var>) coordinates.
@@ -241,7 +228,7 @@ public class Mercator extends Normalized
@Override
public MathTransform createMapProjection(final MathTransformFactory factory) throws FactoryException {
Mercator kernel = this;
- if (isSpherical() || (type & SPHERICAL) != 0) {
+ if ((type & SPHERICAL) != 0 || excentricity == 0) {
kernel = new Spherical(this);
}
return context.completeTransform(factory, kernel);
@@ -382,9 +369,6 @@ public class Mercator extends Normalized
*/
Spherical(final Mercator other) {
super(other);
- if ((type & SPHERICAL) == 0) {
- ensureSpherical();
- }
}
/**
@@ -421,7 +405,7 @@ public class Mercator extends Normalized
/*
* Following part is common to all spherical projections: verify, store and return.
*/
- assert ((type & SPHERICAL) != 0)
+ 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) {
@@ -475,7 +459,8 @@ public class Mercator extends Normalized
double x = srcPts[srcOff ];
double y = srcPts[srcOff+1];
y = PI/2 - 2 * atan(exp(-y)); // Part of Snyder (7-4)
- assert ((type & SPHERICAL) != 0) || checkInverseTransform(srcPts, srcOff, dstPts, dstOff, x, y);
+ 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;
}
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -35,7 +35,6 @@ import org.apache.sis.util.Debug;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.parameter.Parameters;
-import org.apache.sis.parameter.DefaultParameterDescriptor;
import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.operation.matrix.Matrices;
@@ -100,7 +99,7 @@ import java.util.Objects;
* org.opengis.referencing.cs.CoordinateSystem) higher level}.</div>
*
* {@code NormalizedProjection} does not store the above cited parameters (central meridian, scale factor, <i>etc.</i>)
- * on intend, in order to make clear that those parameters are not used by subclasses.
+ * on intend (except indirectly), in order to make clear that those parameters are not used by subclasses.
* The ability to recognize two {@code NormalizedProjection}s as {@linkplain #equals(Object, ComparisonMode) equivalent}
* without consideration for the scale factor (among other) allow more efficient concatenation in some cases
* (typically some combinations of inverse projection followed by a direct projection).
@@ -190,42 +189,130 @@ public abstract class NormalizedProjecti
* <ul>
* <li>On the <b>normalization</b> matrix (to be applied before {@code this} transform):
* <ul>
- * <li>Nothing. Callers shall invoke {@link ContextualParameters#normalizeGeographicInputs(double)} themselves.</li>
+ * <li>{@linkplain ContextualParameters#normalizeGeographicInputs(double) Subtract}
+ * the <cite>central meridian</cite> value.</li>
+ * <li>Convert from degrees to radians.</li>
* </ul>
* </li>
* <li>On the <b>denormalization</b> matrix (to be applied after {@code this} transform):
* <ul>
* <li>{@linkplain ContextualParameters#scaleAndTranslate2D(boolean, double, double, double) Scale}
* by the <cite>semi-major</cite> axis length.</li>
- * <li>Translate by the false easting and false northing (after the scale).</li>
+ * <li>Translate by the <cite>false easting</cite> and <cite>false northing</cite> (after the scale).</li>
* </ul>
* </li>
* <li>On the <b>contextual parameters</b> (not the parameters of {@code this} transform):
* <ul>
* <li>Store the values for <cite>semi-major</cite> axis length, <cite>semi-minor</cite> axis length,
- * <cite>false easting</cite> and <cite>false northing</cite>.</li>
+ * <cite>central meridian</cite>, <cite>false easting</cite> and <cite>false northing</cite> values.</li>
* </ul>
* </li>
* </ul>
*
- * @param method Description of the map projection parameters.
- * @param parameters The parameters of the projection to be created.
- * @param falseEasting The descriptor for fetching the <cite>false easting</cite> parameter.
- * @param falseNorthing The descriptor for fetching the <cite>false northing</cite> parameter.
+ * <div class="section">Pre-requite</div>
+ * The parameters of the given {@code method} argument shall contains descriptor for the given parameters
+ * (using OGC names):
+ * <ul>
+ * <li>{@code "semi_major"}</li>
+ * <li>{@code "semi_minor"}</li>
+ * <li>{@code "central_meridian"}</li>
+ * <li>{@code "false_easting"}</li>
+ * <li>{@code "false_northing"}</li>
+ * </ul>
+ *
+ * <div class="note"><b>Note:</b>
+ * Apache SIS uses EPSG names as much as possible, but this constructor is an exception to this rule.
+ * In this particular case we use OGC names because they are identical for a wide range of projections.
+ * For example there is at least two different EPSG names for the <cite>false northing</cite> parameter,
+ * depending on the projection:
+ *
+ * <ul>
+ * <li><cite>Northing at false origin</cite></li>
+ * <li><cite>Northing at projection centre</cite></li>
+ * </ul>
+ *
+ * OGC defines only {@code "false_northing"} for all, which makes a convenient name to look for in this
+ * constructor.</div>
+ *
+ * @param method Description of the map projection parameters.
+ * @param parameters The parameters of the projection to be created.
+ */
+ protected NormalizedProjection(final OperationMethod method, final Parameters parameters) {
+ this(method, parameters, null,
+ descriptor(method, Constants.FALSE_EASTING),
+ descriptor(method, Constants.FALSE_NORTHING));
+ context.normalizeGeographicInputs(getAndStore(parameters, descriptor(method, Constants.CENTRAL_MERIDIAN)));
+ }
+
+ /**
+ * Returns the parameter descriptor for the given name.
+ * This is a helper method for above constructor only.
*/
- protected NormalizedProjection(final OperationMethod method, final Parameters parameters,
+ private static ParameterDescriptor<Double> descriptor(final OperationMethod method, final String name) {
+ ensureNonNull("method", method);
+ return Parameters.cast((ParameterDescriptor<?>) method.getParameters().descriptor(name), Double.class);
+ }
+
+ /**
+ * Constructs a new map projection by fetching the values using the given parameter descriptors.
+ * At the difference of the {@link #NormalizedProjection(OperationMethod, Parameters)} constructor,
+ * this constructor does <strong>not</strong> apply the following operations:
+ *
+ * <ul>
+ * <li>Normalization: no operation done. Callers shall invoke
+ * {@link ContextualParameters#normalizeGeographicInputs(double)} themselves.</li>
+ * </ul>
+ *
+ *
+ * <div class="section">Radius of conformal sphere (Rc)</div>
+ * If the {@code conformalSphereAtφ} argument is non-null, then the radius of the conformal sphere
+ * at latitude φ will be used instead than the semi-major axis length <var>a</var> (<b>Source:</b>
+ * <cite>Geomatics Guidance Note Number 7, part 2, version 49</cite> from EPSG: table 3 in section
+ * 1.2 and explanation in section 1.3.3.1).
+ *
+ * <p><b>Important usage notes:</b><p>
+ * <ul>
+ * <li>The {@code conformalSphereAtφ} argument shall be non-null <strong>only</strong> when the user
+ * requested explicitely spherical formulas, for example the <cite>"Mercator (Spherical)"</cite>
+ * projection (EPSG:1026), but the figure of the Earth is an ellipsoid rather than a sphere.</li>
+ * <li>This parameter value is <strong>not</strong> stored since we presume that the caller will fetch
+ * the value for its own processing.</li>
+ * </ul>
+ *
+ * @param conformalSphere_φ If non-null, the the latitude where to compute the radius of conformal sphere.
+ * @param falseEasting The descriptor for fetching the <cite>"False easting"</cite> parameter.
+ * @param falseNorthing The descriptor for fetching the <cite>"False northing"</cite> parameter.
+ */
+ NormalizedProjection(final OperationMethod method, final Parameters parameters,
+ final ParameterDescriptor<Double> conformalSphere_φ,
final ParameterDescriptor<Double> falseEasting,
final ParameterDescriptor<Double> falseNorthing)
{
ensureNonNull("parameters", parameters);
context = new ContextualParameters(method);
- final double a = getAndStore(parameters, MapProjection.SEMI_MAJOR);
+ double a = getAndStore(parameters, MapProjection.SEMI_MAJOR);
final double b = getAndStore(parameters, MapProjection.SEMI_MINOR);
final double fe = getAndStore(parameters, falseEasting);
final double fn = getAndStore(parameters, falseNorthing);
- context.scaleAndTranslate2D(false, a, fe, fn);
- excentricitySquared = 1.0 - (b*b) / (a*a);
+ final double rs = b / a;
+ excentricitySquared = 1 - (rs * rs);
excentricity = sqrt(excentricitySquared);
+ if (conformalSphere_φ != null && excentricitySquared != 0) {
+ /*
+ * EPSG said: R is the radius of the sphere and will normally be one of the CRS parameters.
+ * If the figure of the earth used is an ellipsoid rather than a sphere then R should be calculated
+ * as the radius of the conformal sphere at the projection origin at latitude φ₀ using the formula
+ * for Rc given in section 1.2, table 3.
+ *
+ * Table 3 gives:
+ * Radius of conformal sphere Rc = a √(1 – ℯ²) / (1 – ℯ²⋅sin²φ)
+ *
+ * Using √(1 – ℯ²) = b/a we rewrite as: Rc = b / (1 – ℯ²⋅sin²φ)
+ */
+ final double sinφ = sin(toRadians(parameters.doubleValue(conformalSphere_φ)));
+ a = b / (1 - excentricitySquared * (sinφ*sinφ));
+ }
+ context.scaleAndTranslate2D(false, a, fe, fn);
inverse = new Inverse();
}
@@ -263,23 +350,6 @@ public abstract class NormalizedProjecti
}
/**
- * Returns a parameter descriptor with the same properties than the given one, except that the parameter is
- * optional. This is sometime needed when invoking {@link #getAndStore(Parameters, ParameterDescriptor)} for
- * a parameter value which is mandatory in principle, but may be absent because the parameters for the same
- * projection may be specified in different ways (for example <cite>"Mercator (variant A)"</cite> versus
- * <cite>"Mercator (variant B)"</cite>).
- *
- * @param <T> The type of parameter value.
- * @param descriptor The mandatory descriptor to make optional.
- * @return A parameter descriptor with the same properties than the given one, but optional.
- */
- static <T> ParameterDescriptor<T> makeOptional(final ParameterDescriptor<T> descriptor) {
- assert descriptor.getMinimumOccurs() == 1; // This method is useless if minOccurs == 0.
- return new DefaultParameterDescriptor<>(IdentifiedObjects.getProperties(descriptor), 0, 1,
- descriptor.getValueClass(), Parameters.getValueDomain(descriptor), null, descriptor.getDefaultValue());
- }
-
- /**
* Gets a parameter value identified by the given descriptor and stores it in the {@link #context}.
* A "contextual parameter" is a parameter that apply to the normalize → {@code this} → denormalize
* chain as a whole. It does not really apply to this {@code NormalizedProjection} instance when taken alone.
@@ -287,36 +357,7 @@ public abstract class NormalizedProjecti
* <p>This method shall be invoked at construction time only.</p>
*/
final double getAndStore(final Parameters parameters, final ParameterDescriptor<Double> descriptor) {
- final double value = parameters.doubleValue(descriptor); // Apply a unit conversion if needed.
- final Comparable<Double> min = descriptor.getMinimumValue();
- final Comparable<Double> max = descriptor.getMaximumValue();
- if (!Objects.equals(min, max)) {
- /*
- * Why we do not check the bounds in min == max:
- * The only case when our descriptor have (min == max) is when a parameter can only be zero,
- * because of the way the map projection is defined. But in some cases, it would be possible
- * to deal with non-zero values, even if in principle we should not. In such case we let the
- * caller decides.
- */
- if (min instanceof Number && !(value >= ((Number) min).doubleValue())) {
- throw outOfBounds(descriptor, value);
- }
- if (max instanceof Number && !(value <= ((Number) max).doubleValue())) {
- throw outOfBounds(descriptor, value);
- }
- }
- final Double defaultValue = descriptor.getDefaultValue();
- if (defaultValue == null || !defaultValue.equals(value)) {
- context.parameter(descriptor.getName().getCode()).setValue(value);
- }
- return value;
- }
-
- /**
- * Creates the exception for a parameter value out of bounds.
- */
- private static IllegalArgumentException outOfBounds(final ParameterDescriptor<Double> descriptor, double value) {
- return new IllegalArgumentException(Errors.format(Errors.Keys.IllegalParameterValue_2, descriptor.getName(), value));
+ return MapProjection.getAndStore(parameters, context, descriptor);
}
/**
@@ -333,7 +374,7 @@ public abstract class NormalizedProjecti
*
* Subclasses can override this method if they wish to use alternative implementations under some circumstances.
* For example many subclasses will replace {@code this} by a specialized implementation if they detect that the
- * ellipsoid is actually {@linkplain #isSpherical() spherical}.
+ * ellipsoid is actually spherical.
*
* @param factory The factory to use for creating the transform.
* @return The map projection from (λ,φ) to (<var>x</var>,<var>y</var>) coordinates.
@@ -413,28 +454,6 @@ public abstract class NormalizedProjecti
}
/**
- * Returns {@code true} if this projection is done on a sphere rather than an ellipsoid.
- * Projections on spheres have an {@linkplain #excentricity} equals to zero.
- *
- * @return {@code true} if this projection is on a sphere.
- */
- public final boolean isSpherical() {
- return excentricity == 0;
- }
-
- /**
- * Ensures that this projection is done on a sphere rather than an ellipsoid.
- * This method is invoked by constructors of classes implementing only spherical formulas.
- *
- * @throws IllegalArgumentException If the projection is not done on a sphere.
- */
- final void ensureSpherical() throws IllegalArgumentException {
- if (!isSpherical()) {
- throw new IllegalArgumentException(Errors.format(Errors.Keys.EllipticalNotSupported));
- }
- }
-
- /**
* Converts a single coordinate in {@code srcPts} at the given offset and stores the result
* in {@code dstPts} at the given offset. In addition, opportunistically computes the
* transform derivative if requested.
@@ -657,21 +676,6 @@ public abstract class NormalizedProjecti
}
/**
- * Computes the radius of conformal sphere (Rc) at latitude φ. This is used when the user requested
- * explicitely spherical formulas for example with <cite>"Mercator (Spherical)"</cite> projection
- * (EPSG:1026), but the figure of the Earth used is an ellipsoid rather than a sphere.
- *
- * <p><b>Source:</b> <cite>Geomatics Guidance Note Number 7, part 2, version 49</cite> from EPSG:
- * table 3 in section 1.2 and explanation in section 1.3.3.1.</p>
- *
- * @param sinφ The sine of the φ latitude in radians.
- * @return Radius of conformal sphere at latitude φ.
- */
- final double radiusOfConformalSphere(final double sinφ) {
- return sqrt(1 - excentricitySquared) / (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.
Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -28,8 +28,7 @@ import org.apache.sis.test.TestCase;
import org.junit.Test;
import static org.junit.Assert.*;
-import static org.apache.sis.internal.util.Constants.SEMI_MAJOR;
-import static org.apache.sis.internal.util.Constants.SEMI_MINOR;
+import static org.apache.sis.internal.util.Constants.*;
/**
@@ -57,14 +56,14 @@ public final strictfp class MapProjectio
@DependsOnMethod("testSemiAxes")
public void testMercator1SP() {
final Iterator<GeneralParameterDescriptor> it = Mercator1SP.PARAMETERS.descriptors().iterator();
- assertParamEquals("Mercator (variant A)", "Mercator_1SP", true, Mercator1SP.PARAMETERS);
- assertParamEquals(null, SEMI_MAJOR, true, it.next());
- assertParamEquals(null, SEMI_MINOR, true, it.next());
- assertParamEquals("Latitude of natural origin", "latitude_of_origin", true, it.next());
- assertParamEquals("Longitude of natural origin", "central_meridian", true, it.next());
- assertParamEquals("Scale factor at natural origin", "scale_factor", true, it.next());
- assertParamEquals("False easting", "false_easting", true, it.next());
- assertParamEquals("False northing", "false_northing", true, it.next());
+ assertParamEquals("Mercator (variant A)", "Mercator_1SP", true, Mercator1SP.PARAMETERS);
+ assertParamEquals(null, SEMI_MAJOR, true, it.next());
+ assertParamEquals(null, SEMI_MINOR, true, it.next());
+ assertParamEquals("Latitude of natural origin", "latitude_of_origin", true, it.next());
+ assertParamEquals("Longitude of natural origin", CENTRAL_MERIDIAN, true, it.next());
+ assertParamEquals("Scale factor at natural origin", SCALE_FACTOR, true, it.next());
+ assertParamEquals("False easting", FALSE_EASTING, true, it.next());
+ assertParamEquals("False northing", FALSE_NORTHING, true, it.next());
assertFalse(it.hasNext());
assertIsForcedToZero((ParameterDescriptor<?>) Mercator1SP.PARAMETERS.descriptor("latitude_of_origin"));
}
@@ -76,15 +75,15 @@ public final strictfp class MapProjectio
@DependsOnMethod("testSemiAxes")
public void testMercator2SP() {
final Iterator<GeneralParameterDescriptor> it = Mercator2SP.PARAMETERS.descriptors().iterator();
- assertParamEquals("Mercator (variant B)", "Mercator_2SP", true, Mercator2SP.PARAMETERS);
- assertParamEquals(null, SEMI_MAJOR, true, it.next());
- assertParamEquals(null, SEMI_MINOR, true, it.next());
- assertParamEquals("Latitude of 1st standard parallel", "standard_parallel_1", true, it.next());
- assertParamEquals(null, "latitude_of_origin", false, it.next());
- assertParamEquals("Longitude of natural origin", "central_meridian", true, it.next());
- assertParamEquals(null, "scale_factor", false, it.next());
- assertParamEquals("False easting", "false_easting", true, it.next());
- assertParamEquals("False northing", "false_northing", true, it.next());
+ assertParamEquals("Mercator (variant B)", "Mercator_2SP", true, Mercator2SP.PARAMETERS);
+ assertParamEquals(null, SEMI_MAJOR, true, it.next());
+ assertParamEquals(null, SEMI_MINOR, true, it.next());
+ assertParamEquals("Latitude of 1st standard parallel", STANDARD_PARALLEL_1, true, it.next());
+ assertParamEquals(null, "latitude_of_origin", false, it.next());
+ assertParamEquals("Longitude of natural origin", CENTRAL_MERIDIAN, true, it.next());
+ assertParamEquals(null, SCALE_FACTOR, false, it.next());
+ assertParamEquals("False easting", FALSE_EASTING, true, it.next());
+ assertParamEquals("False northing", FALSE_NORTHING, true, it.next());
assertFalse(it.hasNext());
assertIsForcedToZero((ParameterDescriptor<?>) Mercator1SP.PARAMETERS.descriptor("latitude_of_origin"));
}
Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -26,6 +26,14 @@ import org.apache.sis.test.TestCase;
import org.junit.Test;
import static org.junit.Assert.*;
+import static org.apache.sis.internal.util.Constants.SEMI_MAJOR;
+import static org.apache.sis.internal.util.Constants.SEMI_MINOR;
+import static org.apache.sis.internal.util.Constants.CENTRAL_MERIDIAN;
+import static org.apache.sis.internal.util.Constants.STANDARD_PARALLEL_1;
+import static org.apache.sis.internal.util.Constants.STANDARD_PARALLEL_2;
+import static org.apache.sis.parameter.MapProjectionDescriptor.EARTH_RADIUS;
+import static org.apache.sis.parameter.MapProjectionDescriptor.INVERSE_FLATTENING;
+import static org.apache.sis.parameter.MapProjectionDescriptor.STANDARD_PARALLEL;
/**
@@ -49,9 +57,9 @@ public final strictfp class MapProjectio
final ParameterDescriptor<?>[] parameters = new ParameterDescriptor<?>[numStandardParallels + 1];
switch (numStandardParallels) {
default: throw new IllegalArgumentException();
- case 2: parameters[2] = parameter("standard_parallel_2"); // Fall through
- case 1: parameters[1] = parameter("standard_parallel_1"); // Fall through
- case 0: parameters[0] = parameter("central_meridian");
+ case 2: parameters[2] = parameter(STANDARD_PARALLEL_2); // Fall through
+ case 1: parameters[1] = parameter(STANDARD_PARALLEL_1); // Fall through
+ case 0: parameters[0] = parameter(CENTRAL_MERIDIAN);
break;
}
return new MapProjectionDescriptor(name("Lambert Conic Conformal (2SP)"), parameters);
@@ -75,16 +83,16 @@ public final strictfp class MapProjectio
final MapProjectionDescriptor descriptor = createDescriptor(0);
final ParameterValueGroup parameters = descriptor.createValue();
- parameters.parameter("semi_major").setValue(6378137.000); // WGS84
- parameters.parameter("semi_minor").setValue(6356752.314);
- assertEquals(6371007, parameters.parameter("earth_radius").doubleValue(), 0.5); // Authalic radius.
- assertEquals(6378137, parameters.parameter("semi_major") .doubleValue(), 0.5);
- assertEquals(6356752, parameters.parameter("semi_minor") .doubleValue(), 0.5);
-
- parameters.parameter("earth_radius").setValue(6371000);
- assertEquals(6371000, parameters.parameter("earth_radius").doubleValue(), 0.0);
- assertEquals(6371000, parameters.parameter("semi_major") .doubleValue(), 0.0);
- assertEquals(6371000, parameters.parameter("semi_minor") .doubleValue(), 0.0);
+ parameters.parameter(SEMI_MAJOR).setValue(6378137.000); // WGS84
+ parameters.parameter(SEMI_MINOR).setValue(6356752.314);
+ assertEquals(6371007, parameters.parameter(EARTH_RADIUS).doubleValue(), 0.5); // Authalic radius.
+ assertEquals(6378137, parameters.parameter(SEMI_MAJOR) .doubleValue(), 0.5);
+ assertEquals(6356752, parameters.parameter(SEMI_MINOR) .doubleValue(), 0.5);
+
+ parameters.parameter(EARTH_RADIUS).setValue(6371000);
+ assertEquals(6371000, parameters.parameter(EARTH_RADIUS).doubleValue(), 0.0);
+ assertEquals(6371000, parameters.parameter(SEMI_MAJOR) .doubleValue(), 0.0);
+ assertEquals(6371000, parameters.parameter(SEMI_MINOR) .doubleValue(), 0.0);
}
/**
@@ -95,17 +103,17 @@ public final strictfp class MapProjectio
final MapProjectionDescriptor descriptor = createDescriptor(0);
final ParameterValueGroup parameters = descriptor.createValue();
- parameters.parameter("semi_major").setValue(6378206.4); // Clarke 1866
- parameters.parameter("semi_minor").setValue(6356583.8);
- assertEquals(294.97870, parameters.parameter("inverse_flattening").doubleValue(), 0.00001);
- assertEquals(6378206.4, parameters.parameter("semi_major") .doubleValue(), 0.5);
- assertEquals(6356583.8, parameters.parameter("semi_minor") .doubleValue(), 0.5);
-
- parameters.parameter("semi_major").setValue(6378137.000); // WGS84
- parameters.parameter("inverse_flattening").setValue(298.257223563);
- assertEquals(298.257, parameters.parameter("inverse_flattening").doubleValue(), 0.001);
- assertEquals(6378137, parameters.parameter("semi_major") .doubleValue(), 0.5);
- assertEquals(6356752, parameters.parameter("semi_minor") .doubleValue(), 0.5);
+ parameters.parameter(SEMI_MAJOR).setValue(6378206.4); // Clarke 1866
+ parameters.parameter(SEMI_MINOR).setValue(6356583.8);
+ assertEquals(294.97870, parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.00001);
+ assertEquals(6378206.4, parameters.parameter(SEMI_MAJOR) .doubleValue(), 0.5);
+ assertEquals(6356583.8, parameters.parameter(SEMI_MINOR) .doubleValue(), 0.5);
+
+ parameters.parameter(SEMI_MAJOR).setValue(6378137.000); // WGS84
+ parameters.parameter(INVERSE_FLATTENING).setValue(298.257223563);
+ assertEquals(298.257, parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.001);
+ assertEquals(6378137, parameters.parameter(SEMI_MAJOR) .doubleValue(), 0.5);
+ assertEquals(6356752, parameters.parameter(SEMI_MINOR) .doubleValue(), 0.5);
}
/**
@@ -117,11 +125,11 @@ public final strictfp class MapProjectio
final MapProjectionDescriptor descriptor = createDescriptor(0);
final ParameterValueGroup parameters = descriptor.createValue();
- parameters.parameter("semi_major").setValue(6378137.000); // WGS84
- parameters.parameter("inverse_flattening").setValue(298.257223563);
- assertEquals(298.257, parameters.parameter("inverse_flattening").doubleValue(), 0.001);
- assertEquals(6378137, parameters.parameter("semi_major") .doubleValue(), 0.5);
- assertEquals(6356752, parameters.parameter("semi_minor") .doubleValue(), 0.5);
+ parameters.parameter(SEMI_MAJOR).setValue(6378137.000); // WGS84
+ parameters.parameter(INVERSE_FLATTENING).setValue(298.257223563);
+ assertEquals(298.257, parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.001);
+ assertEquals(6378137, parameters.parameter(SEMI_MAJOR) .doubleValue(), 0.5);
+ assertEquals(6356752, parameters.parameter(SEMI_MINOR) .doubleValue(), 0.5);
}
/**
@@ -131,12 +139,15 @@ public final strictfp class MapProjectio
public void testStandardParallel() {
final MapProjectionDescriptor descriptor = createDescriptor(2);
final ParameterValueGroup parameters = descriptor.createValue();
- final ParameterValue<?> p = parameters.parameter("standard_parallel" );
- final ParameterValue<?> p1 = parameters.parameter("standard_parallel_1");
- final ParameterValue<?> p2 = parameters.parameter("standard_parallel_2");
- assertSame(p, parameters.parameter("standard_parallel" ));
- assertSame(p1, parameters.parameter("standard_parallel_1"));
- assertSame(p2, parameters.parameter("standard_parallel_2"));
+ final ParameterValue<?> p = parameters.parameter(STANDARD_PARALLEL);
+ final ParameterValue<?> p1 = parameters.parameter(STANDARD_PARALLEL_1);
+ final ParameterValue<?> p2 = parameters.parameter(STANDARD_PARALLEL_2);
+ assertSame(p, parameters.parameter(STANDARD_PARALLEL));
+ assertSame(p1, parameters.parameter(STANDARD_PARALLEL_1));
+ assertSame(p2, parameters.parameter(STANDARD_PARALLEL_2));
+ assertNotSame(p1, p2);
+ assertNotSame(p1, p);
+ assertNotSame(p2, p);
/* Empty */ assertArrayEquals(new double[] { }, p.doubleValueList(), 0.0);
p1.setValue(40); assertArrayEquals(new double[] {40 }, p.doubleValueList(), 0.0);
Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -75,10 +75,10 @@ strictfp class MapProjectionTestCase ext
*/
final void initialize(final MapProjection provider, final boolean ellipse) throws FactoryException {
final Parameters parameters = parameters(provider, ellipse);
- parameters.parameter("central_meridian").setValue(0.5, NonSI.DEGREE_ANGLE);
- parameters.parameter("scale_factor") .setValue(0.997);
- parameters.parameter("false_easting") .setValue(200);
- parameters.parameter("false_northing") .setValue(100);
+ parameters.parameter(Constants.CENTRAL_MERIDIAN).setValue(0.5, NonSI.DEGREE_ANGLE);
+ parameters.parameter(Constants.SCALE_FACTOR) .setValue(0.997);
+ parameters.parameter(Constants.FALSE_EASTING) .setValue(200);
+ parameters.parameter(Constants.FALSE_NORTHING) .setValue(100);
transform = new MathTransformFactoryMock(provider).createParameterizedTransform(parameters);
}
}
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=1671939&r1=1671938&r2=1671939&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] Tue Apr 7 20:28:42 2015
@@ -57,7 +57,7 @@ final strictfp class NoOp extends Normal
private NoOp(final Parameters parameters) {
super(new DefaultOperationMethod(
Collections.singletonMap(DefaultOperationMethod.NAME_KEY, parameters.getDescriptor().getName()),
- 2, 2, parameters.getDescriptor()), parameters,
+ 2, 2, parameters.getDescriptor()), parameters, null,
MapProjection.SEMI_MAJOR, // Should actually by FALSE_EASTING, but we do not care for this test.
MapProjection.SEMI_MINOR); // Should actually by FALSE_NORTHING, but we do not care for this test.
}
Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -107,11 +107,9 @@ public final strictfp class NormalizedPr
public void testExcentricity() {
NormalizedProjection projection;
transform = projection = new NoOp(false);
- assertTrue("isSpherical", projection.isSpherical());
assertEquals("excentricity", 0.0, projection.excentricity, 0.0);
transform = projection = new NoOp(true);
- assertFalse("isSpherical", projection.isSpherical());
assertEquals("excentricity", 0.08181919084262157, projection.excentricity, TOLERANCE);
}
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java?rev=1671939&r1=1671938&r2=1671939&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java [UTF-8] Tue Apr 7 20:28:42 2015
@@ -78,12 +78,48 @@ public final class Constants extends Sta
SEMI_MINOR = "semi_minor";
/**
+ * The OGC parameter name for the central meridian.
+ */
+ public static final String CENTRAL_MERIDIAN = "central_meridian";
+
+ /**
* The OGC parameter name for the standard parallels.
*/
public static final String STANDARD_PARALLEL_1 = "standard_parallel_1",
STANDARD_PARALLEL_2 = "standard_parallel_2";
/**
+ * The OGC parameter name for the scale factor.
+ * While Apache SIS uses EPSG names when possible, the OGC names are convenient in this case
+ * because they do not depend on the projection. For example EPSG has at least three different
+ * names for the scale factor, depending on the projection:
+ *
+ * <ul>
+ * <li><cite>Scale factor at natural origin</cite></li>
+ * <li><cite>Scale factor on initial line</cite></li>
+ * <li><cite>Scale factor on pseudo standard parallel</cite></li>
+ * </ul>
+ *
+ * Usage of OGC names avoid the need to choose a name according the projection.
+ */
+ public static final String SCALE_FACTOR = "scale_factor";
+
+ /**
+ * The OGC parameter name for the false easting or northing.
+ * While Apache SIS uses EPSG names when possible, the OGC names are convenient in this case
+ * because they do not depend on the projection. For example EPSG has at least two different
+ * names for false northing, depending on the projection:
+ *
+ * <ul>
+ * <li><cite>Northing at false origin</cite></li>
+ * <li><cite>Northing at projection centre</cite></li>
+ * </ul>
+ *
+ * Usage of OGC names avoid the need to choose a name according the projection.
+ */
+ public static final String FALSE_EASTING = "false_easting",
+ FALSE_NORTHING = "false_northing";
+ /**
* Name of the {@value} matrix parameters.
*/
public static final String NUM_ROW = "num_row",