Author: desruisseaux
Date: Mon Mar 21 13:49:07 2016
New Revision: 1735974
URL: http://svn.apache.org/viewvc?rev=1735974&view=rev
Log:
Complete CoordinateOperationInference.createOperationStep(GeocentricCRS,
GeocentricCRS)
including longitude rotation and change of coordinate system (Cartesian <->
Spherical).
This work required a clarification of the condition for using the Bursa-Wolf
parameters.
In order to avoid ambiguities, we use those parameters only if there is no
longitude rotation,
or if the target datum use the Greenwich prime meridian. Otherwise the
parameters are ignored
and the transformation will be reported to have a lower accuracy.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -72,7 +72,7 @@ public final class ExtentSelector<T> {
*/
public boolean evaluate(final Extent extent, final T object) {
final double area =
Extents.area(Extents.intersection(Extents.getGeographicBoundingBox(extent),
areaOfInterest));
- if (best != null && !(area > largestArea)) { // Use '!' for catching
NaN.
+ if (best != null && !(area > largestArea)) { // Use '!' for
catching NaN.
/*
* At this point, the given extent is not greater than the
previous one.
* However if the previous object had no extent information at all
(i.e.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -65,14 +65,16 @@ public final class ReferencingUtilities
* This method provides the same functionality than {@link
DefaultPrimeMeridian#getGreenwichLongitude(Unit)},
* but on arbitrary implementation.
*
- * @param primeMeridian The prime meridian from which to get the
Greenwich longitude.
+ * @param primeMeridian The prime meridian from which to get the
Greenwich longitude, or {@code null}.
* @param unit The unit for the prime meridian to return.
- * @return The prime meridian in the given units.
+ * @return The prime meridian in the given units, or {@code 0} if the
given prime meridian was null.
*
* @see DefaultPrimeMeridian#getGreenwichLongitude(Unit)
*/
public static double getGreenwichLongitude(final PrimeMeridian
primeMeridian, final Unit<Angle> unit) {
- if (primeMeridian instanceof DefaultPrimeMeridian) { // Maybe the user
overrode some methods.
+ if (primeMeridian == null) {
+ return 0;
+ } else if (primeMeridian instanceof DefaultPrimeMeridian) { //
Maybe the user overrode some methods.
return ((DefaultPrimeMeridian)
primeMeridian).getGreenwichLongitude(unit);
} else {
return
primeMeridian.getAngularUnit().getConverterTo(unit).convert(primeMeridian.getGreenwichLongitude());
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -21,11 +21,13 @@ import java.util.Arrays;
import java.io.Serializable;
import org.opengis.metadata.extent.Extent;
import org.opengis.referencing.datum.GeodeticDatum;
+import org.opengis.referencing.datum.PrimeMeridian;
import org.opengis.referencing.operation.Matrix;
import org.apache.sis.referencing.operation.matrix.Matrix4;
import org.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.io.wkt.Formatter;
+import org.apache.sis.util.Utilities;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.internal.util.DoubleDouble;
import org.apache.sis.internal.metadata.WKTKeywords;
@@ -123,7 +125,7 @@ import java.util.Objects;
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @since 0.4
- * @version 0.6
+ * @version 0.7
* @module
*
* @see DefaultGeodeticDatum#getBursaWolfParameters()
@@ -226,15 +228,37 @@ public class BursaWolfParameters extends
/**
* Verifies parameters validity after initialization of {@link
DefaultGeodeticDatum}.
- */
- void verify() {
+ * This method requires that the prime meridian of the target datum is
either the same
+ * than the enclosing {@code GeodeticDatum}, or Greenwich. We put this
restriction for
+ * avoiding ambiguity about whether the longitude rotation should be
applied before or
+ * after the datum shift.
+ *
+ * <p>If the target prime meridian is Greenwich, then SIS will assume that
the datum shift
+ * needs to be applied in a coordinate system having Greenwich as the
prime meridian.</p>
+ *
+ * <p><b>Maintenance note:</b>
+ * if the above policy regarding prime meridians is modified, then some
{@code createOperationStep(…)} method
+ * implementations in {@link
org.apache.sis.referencing.operation.CoordinateOperationInference} may need to
be
+ * revisited. See especially the methods creating a transformation between
a pair of {@code GeocentricCRS} or
+ * between a pair of {@code GeographicCRS} (tip: search for {@code
DefaultGeodeticDatum}).</p>
+ *
+ * @param pm The prime meridian of the enclosing {@code GeodeticDatum}.
+ */
+ void verify(final PrimeMeridian pm) throws IllegalArgumentException {
+ if (targetDatum != null) {
+ final PrimeMeridian actual = targetDatum.getPrimeMeridian();
+ if (actual.getGreenwichLongitude() != 0 &&
!Utilities.equalsIgnoreMetadata(pm, actual)) {
+ throw new
IllegalArgumentException(Errors.format(Errors.Keys.MismatchedPrimeMeridian_2,
+ IdentifiedObjects.getName(pm, null),
IdentifiedObjects.getName(actual, null)));
+ }
+ }
ensureFinite("tX", tX);
ensureFinite("tY", tY);
ensureFinite("tZ", tZ);
ensureFinite("rX", rX);
ensureFinite("rY", rY);
ensureFinite("rZ", rZ);
- ensureBetween("dS", -PPM, PPM, dS); // For preventing zero or negative
value on the matrix diagonal.
+ ensureBetween("dS", -PPM, PPM, dS); // For preventing zero or
negative value on the matrix diagonal.
}
/**
@@ -276,7 +300,7 @@ public class BursaWolfParameters extends
public double[] getValues() {
final double[] elements = new double[(dS != 0) ? 7 : (rZ != 0 || rY !=
0 || rX != 0) ? 6 : 3];
switch (elements.length) {
- default: elements[6] = dS; // Fallthrough everywhere.
+ default: elements[6] = dS; // Fallthrough everywhere.
case 6: elements[5] = rZ;
elements[4] = rY;
elements[3] = rX;
@@ -307,7 +331,7 @@ public class BursaWolfParameters extends
@SuppressWarnings("fallthrough")
public void setValues(final double... elements) {
switch (elements.length) {
- default: dS = elements[6]; // Fallthrough everywhere.
+ default: dS = elements[6]; // Fallthrough everywhere.
case 6: rZ = elements[5];
case 5: rY = elements[4];
case 4: rX = elements[3];
@@ -543,17 +567,17 @@ public class BursaWolfParameters extends
}
for (int i = j+1; i < SIZE-1; i++) {
S.setFrom(RS);
- S.inverseDivide(getNumber(matrix, j,i)); // Negative rotation
term.
+ S.inverseDivide(getNumber(matrix, j,i)); // Negative
rotation term.
double value = S.value;
double error = S.error;
S.setFrom(RS);
- S.inverseDivide(getNumber(matrix, i,j)); // Positive rotation
term.
- if (!(abs(value + S.value) <= tolerance)) { // We expect r1 ≈
-r2
+ S.inverseDivide(getNumber(matrix, i,j)); // Positive
rotation term.
+ if (!(abs(value + S.value) <= tolerance)) { // We expect
r1 ≈ -r2
throw new
IllegalArgumentException(Errors.format(Errors.Keys.NotASkewSymmetricMatrix));
}
S.subtract(value, error);
S.multiply(0.5, 0);
- value = S.value; // Average of the two rotation terms.
+ value = S.value; // Average of
the two rotation terms.
switch (j*SIZE + i) {
case 1: rZ = value; break;
case 2: rY = -value; break;
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -243,6 +243,13 @@ public class DefaultGeodeticDatum extend
* </tr>
* </table>
*
+ * If Bursa-Wolf parameters are specified, then the prime meridian of their
+ * {@linkplain BursaWolfParameters#getTargetDatum() target datum} shall be
either the same than the
+ * {@code primeMeridian} given to this constructor, or Greenwich. This
restriction is for avoiding
+ * ambiguity about whether the longitude rotation shall be applied before
or after the datum shift.
+ * If the target prime meridian is Greenwich, then the datum shift will be
applied in a coordinate
+ * system having Greenwich as the prime meridian.
+ *
* @param properties The properties to be given to the identified
object.
* @param ellipsoid The ellipsoid.
* @param primeMeridian The prime meridian.
@@ -265,7 +272,7 @@ public class DefaultGeodeticDatum extend
BursaWolfParameters param = bursaWolf[i];
ensureNonNullElement("bursaWolf", i, param);
param = param.clone();
- param.verify();
+ param.verify(primeMeridian);
bursaWolf[i] = param;
}
}
@@ -368,12 +375,21 @@ public class DefaultGeodeticDatum extend
* 1033 – <cite>Position Vector transformation (geocentric domain)</cite>,
or
* 1053 – <cite>Time-dependent Position Vector transformation</cite>.
*
- * <p>If this datum and the given {@code targetDatum} do not use the same
- * {@linkplain #getPrimeMeridian() prime meridian}, then it is caller's
responsibility
- * to apply longitude rotation before to use the matrix returned by this
method.</p>
- *
- * <div class="section">Search order</div>
- * This method performs the search in the following order:
+ * <p>If this datum and the given {@code targetDatum} do not use the same
{@linkplain #getPrimeMeridian() prime meridian},
+ * then it is caller's responsibility to to apply longitude rotation
before to use the matrix returned by this method.
+ * The target prime meridian should be Greenwich (see {@linkplain
#DefaultGeodeticDatum(Map, Ellipsoid, PrimeMeridian)
+ * constructor javadoc}), in which case the datum shift should be applied
in a geocentric coordinate system having
+ * Greenwich as the prime meridian.</p>
+ *
+ * <div class="note"><b>Note:</b>
+ * in EPSG dataset version 8.9, all datum shifts that can be represented
by this method use Greenwich as the
+ * prime meridian, both in source and target datum.</div>
+ *
+ * <div class="section">Search criterion</div>
+ * If the given {@code areaOfInterest} is non-null and contains at least
one geographic bounding box, then this
+ * method ignores any Bursa-Wolf parameters having a {@linkplain
BursaWolfParameters#getDomainOfValidity() domain
+ * of validity} that does not intersect the given geographic extent.
+ * This method performs the search among the remaining parameters in the
following order:
* <ol>
* <li>If this {@code GeodeticDatum} contains {@code
BursaWolfParameters} having the given
* {@linkplain BursaWolfParameters#getTargetDatum() target datum}
(ignoring metadata),
@@ -449,7 +465,7 @@ public class DefaultGeodeticDatum extend
* not a subclass of BursaWolfParameters. This optimisation covers the
vast majority of cases.
*/
return bursaWolf.getPositionVectorTransformation(bursaWolf.getClass()
!= BursaWolfParameters.class ?
- Extents.getDate(areaOfInterest, 0.5) : null); // 0.5 is for
choosing midway instant.
+ Extents.getDate(areaOfInterest, 0.5) : null); // 0.5 is
for choosing midway instant.
}
/**
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.datum
import java.util.Date;
import org.opengis.metadata.extent.Extent;
import org.opengis.referencing.datum.GeodeticDatum;
+import org.opengis.referencing.datum.PrimeMeridian;
import org.apache.sis.internal.util.Numerics;
import org.apache.sis.internal.util.DoubleDouble;
@@ -132,8 +133,8 @@ public class TimeDependentBWP extends Bu
* Verifies parameters validity after initialization.
*/
@Override
- void verify() {
- super.verify();
+ void verify(final PrimeMeridian pm) throws IllegalArgumentException {
+ super.verify(pm);
ensureFinite("dtX", dtX);
ensureFinite("dtY", dtY);
ensureFinite("dtZ", dtZ);
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -40,6 +40,18 @@
* DefaultGeodeticDatum.getPositionVectorTransformation(GeodeticDatum,
Extent)}</li>
* </ul>
*
+ * <div class="section">Datum shifts</div>
+ * Three classes are provided in support of coordinate transformations between
different datums:
+ * <ul>
+ * <li>{@link org.apache.sis.referencing.datum.BursaWolfParameters} performs
an approximation
+ * based on a translation, rotation and scale of geocentric
coordinates.</li>
+ * <li>{@link org.apache.sis.referencing.datum.TimeDependentBWP} is like
{@code BursaWolfParameters},
+ * but varies with time for taking in account the motion of plate
tectonic.</li>
+ * <li>{@link org.apache.sis.referencing.datum.DatumShiftGrid} is used for
more accurate transformations
+ * than what {@code BursaWolfParameters} allows, by interpolating the
geographic or geocentric translations
+ * in a grid (e.g. NADCON or NTv2) instead than apply the same
transformation for every points.</li>
+ * </ul>
+ *
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Cédric Briançon (Geomatys)
* @since 0.4
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -17,14 +17,21 @@
package org.apache.sis.referencing.factory.sql;
import java.util.Locale;
+import java.util.List;
+import java.util.Map;
+import java.util.LinkedHashMap;
import java.sql.ResultSet;
import javax.measure.unit.Unit;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.converter.ConversionException;
+import org.opengis.util.FactoryException;
+import org.opengis.metadata.extent.Extent;
+import org.apache.sis.internal.referencing.ExtentSelector;
import org.apache.sis.referencing.datum.BursaWolfParameters;
import org.apache.sis.referencing.datum.TimeDependentBWP;
import org.apache.sis.referencing.factory.FactoryDataException;
+import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.measure.Units;
@@ -123,11 +130,22 @@ final class BursaWolfInfo {
final int target;
/**
+ * The value of {@code AREA_OF_USE_CODE}.
+ */
+ private final int domainOfValidity;
+
+ /**
+ * The domain of validity as an {@code Extent} object.
+ */
+ private Extent extent;
+
+ /**
* Fills a structure with the specified values.
*/
- BursaWolfInfo(final int operation, final int method, final int targetCRS) {
- this.operation = operation;
- this.method = method;
+ BursaWolfInfo(final int operation, final int method, final int targetCRS,
final int domainOfValidity) {
+ this.operation = operation;
+ this.method = method;
+ this.domainOfValidity = domainOfValidity;
switch (targetCRS) {
case TARGET_CRS: target = TARGET_DATUM; break;
// More codes may be added in future SIS version.
@@ -155,4 +173,44 @@ final class BursaWolfInfo {
public String toString() {
return String.valueOf(operation);
}
+
+ /**
+ * Gets the domain of validity. The result is cached.
+ *
+ * @param factory The factory to use for creating {@code Extent} instances.
+ */
+ Extent getDomainOfValidity(final GeodeticAuthorityFactory factory) throws
FactoryException {
+ if (extent == null && domainOfValidity != 0) {
+ extent = factory.createExtent(String.valueOf(domainOfValidity));
+ }
+ return extent;
+ }
+
+ /**
+ * Given an array of {@code BursaWolfInfo} instances, retains only the
instances having the largest
+ * domain of validity for each target datum. If two instances have the
same domain of validity, the
+ * first one is retained. This presume that the instances have already
been sorted for preference order
+ * before to invoke this method.
+ *
+ * @param factory The factory to use for creating {@code Extent}
instances.
+ * @param candidates The Bursa-Wolf parameters candidates.
+ * @param addTo Where to add the instances retained by this method.
+ */
+ static void filter(final GeodeticAuthorityFactory factory, final
BursaWolfInfo[] candidates,
+ final List<BursaWolfInfo> addTo) throws FactoryException
+ {
+ final Map<Integer,ExtentSelector<BursaWolfInfo>> added = new
LinkedHashMap<>();
+ for (BursaWolfInfo candidate : candidates) {
+ final Integer target = candidate.target;
+ ExtentSelector<BursaWolfInfo> selector = added.get(target);
+ if (selector == null) {
+ selector = new ExtentSelector<>(null);
+ added.put(target, selector);
+ }
+ selector.evaluate(candidate.getDomainOfValidity(factory),
candidate);
+ }
+ for (final ExtentSelector<BursaWolfInfo> select : added.values()) {
+ addTo.add(select.best());
+ }
+ }
}
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -19,7 +19,6 @@ package org.apache.sis.referencing.facto
import java.util.Set;
import java.util.Map;
import java.util.List;
-import java.util.HashSet;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedHashMap;
@@ -107,11 +106,13 @@ import org.apache.sis.util.CharSequences
import org.apache.sis.util.Localized;
import org.apache.sis.util.Version;
import org.apache.sis.util.Workaround;
+import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.collection.Containers;
import org.apache.sis.measure.MeasurementRange;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.measure.Units;
+import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
import static
org.apache.sis.internal.referencing.ServicesForMetadata.CONNECTION;
// Branch-dependent imports
@@ -1619,7 +1620,7 @@ addURIs: for (int i=0; ; i++) {
properties = new HashMap<>(properties); //
Protect from changes
final Ellipsoid ellipsoid = owner.createEllipsoid
(getString(code, result, 10));
final PrimeMeridian meridian =
owner.createPrimeMeridian(getString(code, result, 11));
- final BursaWolfParameters[] param =
createBursaWolfParameters(epsg);
+ final BursaWolfParameters[] param =
createBursaWolfParameters(meridian, epsg);
if (param != null) {
properties.put(DefaultGeodeticDatum.BURSA_WOLF_KEY, param);
}
@@ -1690,10 +1691,13 @@ addURIs: for (int i=0; ; i++) {
* That legacy format had a {@code TOWGS84} element which needs the
information provided by this method.
* Note that {@code TOWGS84} is a deprecated element as of WKT 2 (ISO
19162).</p>
*
- * @param code The EPSG code of the {@link GeodeticDatum}.
+ * @param meridian The source datum prime meridian, used for discarding
any target datum using a different meridian.
+ * @param code The EPSG code of the source {@link GeodeticDatum}.
* @return an array of Bursa-Wolf parameters, or {@code null}.
*/
- private BursaWolfParameters[] createBursaWolfParameters(final Integer
code) throws SQLException, FactoryException {
+ private BursaWolfParameters[] createBursaWolfParameters(final
PrimeMeridian meridian, final Integer code)
+ throws SQLException, FactoryException
+ {
/*
* We do not provide TOWGS84 information for WGS84 itself or for any
other datum on our list of target datum,
* in order to avoid infinite recursivity. The 'ensureNonRecursive'
call is an extra safety check which should
@@ -1706,7 +1710,8 @@ addURIs: for (int i=0; ; i++) {
try (ResultSet result = executeQuery("BursaWolfParametersSet",
"SELECT COORD_OP_CODE," +
" COORD_OP_METHOD_CODE," +
- " TARGET_CRS_CODE" +
+ " TARGET_CRS_CODE," +
+ " AREA_OF_USE_CODE"+
" FROM [Coordinate_Operation]" +
" WHERE DEPRECATED=0" + // Do not put spaces around
"=" - SQLTranslator searches for this exact match.
" AND TARGET_CRS_CODE = " + BursaWolfInfo.TARGET_CRS +
@@ -1720,7 +1725,8 @@ addURIs: for (int i=0; ; i++) {
final BursaWolfInfo info = new BursaWolfInfo(
getInteger(code, result, 1), //
Operation
getInteger(code, result, 2), // Method
- getInteger(code, result, 3)); // Target
datum
+ getInteger(code, result, 3), // Target
datum
+ getInteger(code, result, 4)); // Domain
of validity
if (info.target != code) { //
Paranoiac check.
bwInfos.add(info);
}
@@ -1739,12 +1745,7 @@ addURIs: for (int i=0; ; i++) {
final BursaWolfInfo[] codes = bwInfos.toArray(new
BursaWolfInfo[size]);
sort("Coordinate_Operation", codes);
bwInfos.clear();
- final Set<Integer> added = new HashSet<>();
- for (BursaWolfInfo candidate : codes) {
- if (added.add(candidate.target)) {
- bwInfos.add(candidate);
- }
- }
+ BursaWolfInfo.filter(owner, codes, bwInfos);
size = bwInfos.size();
}
/*
@@ -1752,6 +1753,7 @@ addURIs: for (int i=0; ; i++) {
*/
final BursaWolfParameters[] parameters = new BursaWolfParameters[size];
final Locale locale = getLocale();
+ int count = 0;
for (int i=0; i<size; i++) {
final BursaWolfInfo info = bwInfos.get(i);
final GeodeticDatum datum;
@@ -1761,7 +1763,17 @@ addURIs: for (int i=0; ; i++) {
} finally {
endOfRecursivity(BursaWolfParameters.class, code);
}
- final BursaWolfParameters bwp = new BursaWolfParameters(datum,
null);
+ /*
+ * Accept only Bursa-Wolf parameters between datum that use the
same prime meridian.
+ * This is for avoiding ambiguity about whether longitude rotation
should be applied
+ * before or after the datum change. This check is useless for
EPSG dataset 8.9 since
+ * all datum seen by this method use Greenwich. But we
nevertheless perform this check
+ * as a safety for future evolution or customized EPSG dataset.
+ */
+ if (!equalsIgnoreMetadata(meridian, datum.getPrimeMeridian())) {
+ continue;
+ }
+ final BursaWolfParameters bwp = new BursaWolfParameters(datum,
info.getDomainOfValidity(owner));
try (ResultSet result = executeQuery("BursaWolfParameters",
"SELECT PARAMETER_CODE," +
" PARAMETER_VALUE," +
@@ -1782,9 +1794,9 @@ addURIs: for (int i=0; ; i++) {
// except for the sign of rotation parameters.
bwp.reverseRotation();
}
- parameters[i] = bwp;
+ parameters[count++] = bwp;
}
- return parameters;
+ return ArraysExt.resize(parameters, count);
}
/**
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -17,7 +17,11 @@
package org.apache.sis.referencing.operation;
import java.io.Serializable;
+import org.opengis.metadata.extent.Extent;
import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.apache.sis.metadata.iso.extent.DefaultExtent;
+import org.apache.sis.metadata.iso.extent.Extents;
+import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.util.ArgumentChecks;
@@ -57,9 +61,14 @@ public class CoordinateOperationContext
private static final long serialVersionUID = -6944460471653277973L;
/**
- * The area of interest, or {@code null} if none.
+ * The spatio-temporal area of interest, or {@code null} if none.
*/
- private GeographicBoundingBox areaOfInterest;
+ private Extent areaOfInterest;
+
+ /**
+ * The geographic component of the area of interest, computed when first
needed.
+ */
+ private transient GeographicBoundingBox bbox;
/**
* The desired accuracy in metres, or 0 for the best accuracy available.
@@ -80,31 +89,69 @@ public class CoordinateOperationContext
* @param accuracy The desired accuracy in metres, or 0 for the best
accuracy available.
* See {@link #getDesiredAccuracy()} for more details about what we mean
by <cite>"best accuracy"</cite>.
*/
- public CoordinateOperationContext(final GeographicBoundingBox area, final
double accuracy) {
+ public CoordinateOperationContext(final Extent area, final double
accuracy) {
ArgumentChecks.ensurePositive("accuracy", accuracy);
areaOfInterest = area;
desiredAccuracy = accuracy;
}
/**
- * Returns the geographic area of interest, or {@code null} if none.
+ * Returns the spatio-temporal area of interest, or {@code null} if none.
*
- * @return The area of interest, or {@code null} if none.
+ * @return The spatio-temporal area of interest, or {@code null} if none.
*/
- public GeographicBoundingBox getAreaOfInterest() {
+ public Extent getAreaOfInterest() {
return areaOfInterest;
}
/**
- * Sets the geographic area of interest, or {@code null} if none.
+ * Sets the spatio-temporal area of interest, or {@code null} if none.
*
- * @param area The area of interest, or {@code null} if none.
+ * @param area The spatio-temporal area of interest, or {@code null} if
none.
*/
- public void setAreaOfInterest(final GeographicBoundingBox area) {
+ public void setAreaOfInterest(final Extent area) {
areaOfInterest = area;
}
/**
+ * Returns the geographic component of the area of interest, or {@code
null} if none.
+ * This convenience method extracts the bounding box from the
spatio-temporal {@link Extent}.
+ *
+ * @return The geographic area of interest, or {@code null} if none.
+ */
+ public GeographicBoundingBox getGeographicBoundingBox() {
+ if (bbox == null) {
+ bbox = Extents.getGeographicBoundingBox(areaOfInterest);
+ }
+ return bbox;
+ }
+
+ /**
+ * Sets the geographic component of the area of interest, or {@code null}
if none.
+ * This convenience method set the bounding box into the spatio-temporal
{@link Extent}.
+ *
+ * @param area The geographic area of interest, or {@code null} if none.
+ */
+ public void setGeographicBoundingBox(final GeographicBoundingBox area) {
+ areaOfInterest = setGeographicBoundingBox(areaOfInterest, area);
+ bbox = area;
+ }
+
+ /**
+ * Sets the given geographic bounding box in the given extent.
+ */
+ static Extent setGeographicBoundingBox(Extent areaOfInterest, final
GeographicBoundingBox bbox) {
+ if (areaOfInterest != null) {
+ final DefaultExtent ex = DefaultExtent.castOrCopy(areaOfInterest);
+ ex.setGeographicElements(CollectionsExt.singletonOrEmpty(bbox));
+ areaOfInterest = ex;
+ } else if (bbox != null) {
+ areaOfInterest = new DefaultExtent(null, bbox, null, null);
+ }
+ return areaOfInterest;
+ }
+
+ /**
* Returns the desired accuracy in metres.
* A value of 0 means to search for the most accurate operation.
*
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -30,35 +30,39 @@ import org.opengis.referencing.crs.*;
import org.opengis.referencing.datum.*;
import org.opengis.referencing.operation.*;
import org.opengis.metadata.Identifier;
+import org.opengis.metadata.extent.Extent;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.metadata.quality.PositionalAccuracy;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.apache.sis.internal.metadata.ReferencingServices;
-import org.apache.sis.internal.referencing.Formulas;
import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
-import org.apache.sis.internal.referencing.ReferencingUtilities;
import org.apache.sis.internal.referencing.provider.Affine;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.measure.Units;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.metadata.iso.extent.Extents;
import org.apache.sis.parameter.Parameterized;
-import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.NamedIdentifier;
+import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.CoordinateSystems;
import org.apache.sis.referencing.datum.BursaWolfParameters;
import org.apache.sis.referencing.datum.DefaultGeodeticDatum;
+import org.apache.sis.referencing.operation.matrix.Matrix4;
import org.apache.sis.referencing.operation.matrix.Matrices;
-import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+import org.apache.sis.referencing.operation.transform.MathTransforms;
+import
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Classes;
-import org.apache.sis.util.Utilities;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
+import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
+import static
org.apache.sis.internal.referencing.ReferencingUtilities.getGreenwichLongitude;
+
// Branch-dependent imports
import java.util.Objects;
@@ -138,9 +142,14 @@ public class CoordinateOperationInferenc
private final DefaultCoordinateOperationFactory factorySIS;
/**
- * The area of interest, or {@code null} if none.
+ * The spatio-temporal area of interest, or {@code null} if none.
+ */
+ private Extent areaOfInterest;
+
+ /**
+ * The geographic component of the area of interest, or {@code null} if
none.
*/
- private GeographicBoundingBox areaOfInterest;
+ private GeographicBoundingBox bbox;
/**
* The desired accuracy in metres, or 0 for the best accuracy available.
@@ -163,6 +172,7 @@ public class CoordinateOperationInferenc
if (context != null) {
areaOfInterest = context.getAreaOfInterest();
desiredAccuracy = context.getDesiredAccuracy();
+ bbox = context.getGeographicBoundingBox();
}
}
@@ -184,6 +194,19 @@ public class CoordinateOperationInferenc
}
/**
+ * If the domain of interest was not set, defines it to the domain of
validity of the given CRS.
+ */
+ private void updateDomainOfInterest(final CoordinateReferenceSystem
sourceCRS,
+ final CoordinateReferenceSystem
targetCRS)
+ {
+ if (bbox == null) {
+ bbox =
Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS),
+
CRS.getGeographicBoundingBox(targetCRS));
+ areaOfInterest =
CoordinateOperationContext.setGeographicBoundingBox(areaOfInterest, bbox);
+ }
+ }
+
+ /**
* Infers an operation for conversion or transformation between two
coordinate reference systems.
* This method inspects the given CRS and delegates the work to one or
many {@code createOperationStep(…)} methods.
* This method fails if no path between the CRS is found.
@@ -200,10 +223,6 @@ public class CoordinateOperationInferenc
{
ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
- if (areaOfInterest == null) {
- areaOfInterest =
Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS),
-
CRS.getGeographicBoundingBox(targetCRS));
- }
////////////////////////////////////////////////////////////////////////////////
////
////
//// Compound → various CRS
////
@@ -314,71 +333,101 @@ public class CoordinateOperationInferenc
* @param targetCRS output coordinate reference system.
* @return a coordinate operation from {@code sourceCRS} to {@code
targetCRS}.
* @throws FactoryException if the operation can not be constructed.
- *
- * @todo Rotation of prime meridian not yet implemented.
- * @todo Conversion between Cartesian and spherical CS not yet implemented.
*/
protected CoordinateOperation createOperationStep(final GeocentricCRS
sourceCRS,
final GeocentricCRS
targetCRS)
throws FactoryException
{
+ updateDomainOfInterest(sourceCRS, targetCRS);
final GeodeticDatum sourceDatum = sourceCRS.getDatum();
final GeodeticDatum targetDatum = targetCRS.getDatum();
final CoordinateSystem sourceCS = sourceCRS.getCoordinateSystem();
final CoordinateSystem targetCS = targetCRS.getCoordinateSystem();
- if (Utilities.equalsIgnoreMetadata(sourceDatum, targetDatum)) {
+ CoordinateSystem sourceNormalized = null;
+ CoordinateSystem targetNormalized = null;
+ Matrix datumShift = null; // Those 3 variables
will be null or non-null together.
+ /*
+ * If both CRS use the same datum and the same prime meridian, then
the coordinate operation is just
+ * an axis swapping, unit conversion or change between spherical and
Cartesian coordinate system type.
+ * Otherwise (if the datum are not the same), we need to perform a
scale, translation and rotation in
+ * Cartesian space using the Bursa-Wolf parameters.
+ */
+ Identifier identifier;
+ if (equalsIgnoreMetadata(sourceDatum, targetDatum)) {
+ identifier = equalsIgnoreMetadata(sourceCS, targetCS) ? IDENTITY :
AXIS_CHANGES;
+ } else {
+ identifier = ELLIPSOID_CHANGE;
+ if (sourceDatum instanceof DefaultGeodeticDatum) {
+ datumShift = ((DefaultGeodeticDatum)
sourceDatum).getPositionVectorTransformation(targetDatum, areaOfInterest);
+ if (datumShift != null) {
+ identifier = DATUM_SHIFT;
+ sourceNormalized =
CommonCRS.WGS84.geocentric().getCoordinateSystem();
+ targetNormalized = sourceNormalized;
+ }
+ }
/*
- * If both CRS use the same datum and the same prime meridian,
then the coordinate operation is just
- * an axis swapping and unit conversion except if the coordinate
systems are not of the same kind.
+ * If there is a change of prime meridian, concatenate that change
before or after the datum shift.
+ * Actually we do not know if we should concatenate longitude
rotation before or after datum shift.
+ * But this ambiguity does not apply to EPSG dataset 8.9 because
source and target prime meridians
+ * are always Greenwich. For reducing ambiguity in other cases,
the SIS DefaultGeodeticDatum class
+ * ensures that if the prime meridian are not the same, then the
target meridian must be Greenwich.
*/
- final Matrix matrix = swapAndScaleAxes(sourceCS, targetCS);
- return createFromAffineTransform(AXIS_CHANGES, sourceCRS,
targetCRS, matrix);
- }
- if (!isGreenwichLongitudeEquals(sourceDatum.getPrimeMeridian(),
targetDatum.getPrimeMeridian())) {
- throw new OperationNotFoundException("Rotation of prime meridian
not yet implemented");
+ final double sourceMeridian =
getGreenwichLongitude(sourceDatum.getPrimeMeridian(), NonSI.DEGREE_ANGLE);
+ final double targetMeridian =
getGreenwichLongitude(targetDatum.getPrimeMeridian(), NonSI.DEGREE_ANGLE);
+ if (sourceMeridian != targetMeridian) {
+ if (sourceNormalized == null) {
+ sourceNormalized = CoordinateSystems.replaceAxes(sourceCS,
AxesConvention.NORMALIZED);
+ targetNormalized = CoordinateSystems.replaceAxes(targetCS,
AxesConvention.NORMALIZED);
+ }
+ final boolean isTargetCartesian = (targetNormalized instanceof
CartesianCS);
+ if (!(isTargetCartesian || targetNormalized instanceof
SphericalCS)) {
+ throw new
FactoryException(Errors.format(Errors.Keys.IllegalCoordinateSystem_1,
targetCS.getClass()));
+ }
+ final Matrix4 rot = new Matrix4();
+ boolean isSource = true;
+ do { // Executed exactly twice:
once for source, then once for target.
+ double θ = isSource ? sourceMeridian : -targetMeridian;
+ if (θ != 0) {
+ if (isTargetCartesian) {
+ θ = Math.toRadians(θ);
+ rot.m00 = rot.m11 = Math.cos(θ);
+ rot.m01 = -(rot.m10 = Math.sin(θ));
+ } else {
+ rot.m02 = θ;
+ }
+ if (datumShift == null) {
+ datumShift = rot;
+ } else if (isSource) {
+ datumShift = Matrices.multiply(datumShift, rot);
// Apply rotation before datum shift.
+ } else {
+ datumShift = Matrices.multiply(rot, datumShift);
// Apply rotation after datum shift.
+ }
+ }
+ } while ((isSource = !isSource) == false);
+ }
}
/*
- * Transform between differents ellipsoids using Bursa Wolf parameters.
- * The Bursa Wolf parameters are used with "standard" geocentric CS,
i.e.
- * with x axis towards the prime meridian, y axis towards East and z
axis
- * toward North. The following steps are applied:
+ * Transform between differents datums using Bursa Wolf parameters.
The Bursa Wolf parameters are used
+ * with "standard" geocentric CS, i.e. with X axis towards the prime
meridian, Y axis towards East and
+ * Z axis toward North. The following steps are applied:
*
- * source CRS →
- * standard CRS with source datum →
- * standard CRS with target datum →
+ * source CRS →
+ * normalized CRS with source datum →
+ * normalized CRS with target datum →
* target CRS
*/
- Matrix datumShift = null;
- Identifier identifier = DATUM_SHIFT;
- final GeodeticDatum datum = null;//TemporaryDatum.unwrap(sourceDatum);
-// if (datum instanceof DefaultGeodeticDatum) {
-// datumShift = ((DefaultGeodeticDatum)
datum).getPositionVectorTransformation(
-// TemporaryDatum.unwrap(targetDatum), null);
-// }
-// if (datumShift == null) {
-// if (lenientDatumShift) {
-// datumShift = new Matrix4(); // Identity transform.
-// identifier = ELLIPSOID_CHANGE;
-// } else {
-// throw new OperationNotFoundException(Errors.format(
-// Errors.Keys.BursaWolfParametersRequired));
-// }
-// }
- MatrixSIS matrix;
- final CartesianCS standard = (CartesianCS)
CommonCRS.WGS84.geocentric().getCoordinateSystem();
- final Matrix normalizeSource = swapAndScaleAxes(sourceCS, standard);
- final Matrix normalizeTarget = swapAndScaleAxes(standard, targetCS);
- /*
- * Since all steps are matrices, we can multiply them and get a single
matrix.
- * MatrixSIS.multiply(Matrix) is equivalent to
AffineTransform.concatenate(…):
- * First transform by the supplied transform and then transform the
result by
- * the original transform. So we compute;
- *
- * matrix = normalizeTarget × datumShift × normalizeSource
- */
- matrix = Matrices.multiply(normalizeTarget, datumShift);
- matrix = matrix.multiply(normalizeSource);
- return createFromAffineTransform(identifier, sourceCRS, targetCRS,
matrix);
+ MathTransform tr;
+ final DefaultMathTransformFactory mtFactory =
factorySIS.getDefaultMathTransformFactory();
+ if (datumShift != null) {
+ final MathTransform normalize =
mtFactory.createCoordinateSystemChange(sourceCS, sourceNormalized);
+ final MathTransform denormalize =
mtFactory.createCoordinateSystemChange(targetNormalized, targetCS);
+ tr = mtFactory.createAffineTransform(datumShift);
+ tr = mtFactory.createConcatenatedTransform(normalize,
+ mtFactory.createConcatenatedTransform(tr, denormalize));
+ } else {
+ tr = mtFactory.createCoordinateSystemChange(sourceCS, targetCS);
+ }
+ return createFromMathTransform(properties(identifier), sourceCRS,
targetCRS, tr, null, null);
}
/**
@@ -397,14 +446,20 @@ public class CoordinateOperationInferenc
final VerticalCRS
targetCRS)
throws FactoryException
{
+ updateDomainOfInterest(sourceCRS, targetCRS);
final VerticalDatum sourceDatum = sourceCRS.getDatum();
final VerticalDatum targetDatum = targetCRS.getDatum();
- if (!Utilities.equalsIgnoreMetadata(sourceDatum, targetDatum)) {
+ if (!equalsIgnoreMetadata(sourceDatum, targetDatum)) {
throw new OperationNotFoundException(notFoundMessage(sourceDatum,
targetDatum));
}
final VerticalCS sourceCS = sourceCRS.getCoordinateSystem();
final VerticalCS targetCS = targetCRS.getCoordinateSystem();
- final Matrix matrix = swapAndScaleAxes(sourceCS, targetCS);
+ final Matrix matrix;
+ try {
+ matrix = CoordinateSystems.swapAndScaleAxes(sourceCS, targetCS);
+ } catch (IllegalArgumentException | ConversionException exception) {
+ throw new OperationNotFoundException(notFoundMessage(sourceCRS,
targetCRS), exception);
+ }
return createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS,
matrix);
}
@@ -422,6 +477,7 @@ public class CoordinateOperationInferenc
final TemporalCRS
targetCRS)
throws FactoryException
{
+ updateDomainOfInterest(sourceCRS, targetCRS);
final TemporalDatum sourceDatum = sourceCRS.getDatum();
final TemporalDatum targetDatum = targetCRS.getDatum();
final TimeCS sourceCS = sourceCRS.getCoordinateSystem();
@@ -445,7 +501,12 @@ public class CoordinateOperationInferenc
*
* The "epoch shift" previously computed is a translation.
Consequently, it is added to element (0,1).
*/
- final Matrix matrix = swapAndScaleAxes(sourceCS, targetCS);
+ final Matrix matrix;
+ try {
+ matrix = CoordinateSystems.swapAndScaleAxes(sourceCS, targetCS);
+ } catch (IllegalArgumentException | ConversionException exception) {
+ throw new OperationNotFoundException(notFoundMessage(sourceCRS,
targetCRS), exception);
+ }
final int translationColumn = matrix.getNumCol() - 1; //
Paranoiac check: should always be 1.
final double translation = matrix.getElement(0, translationColumn);
matrix.setElement(0, translationColumn, translation + epochShift);
@@ -471,36 +532,8 @@ public class CoordinateOperationInferenc
final Matrix
matrix)
throws FactoryException
{
- final MathTransformFactory mtFactory =
factorySIS.getMathTransformFactory();
- final MathTransform transform =
mtFactory.createAffineTransform(matrix);
- final Map<String,?> properties = properties(name);
- final Class<? extends SingleOperation> type =
-
properties.containsKey(CoordinateOperation.COORDINATE_OPERATION_ACCURACY_KEY)
- ? Transformation.class : Conversion.class;
- return createFromMathTransform(properties, sourceCRS, targetCRS,
transform,
- Affine.getProvider(transform.getSourceDimensions(),
- transform.getTargetDimensions(),
- Matrices.isAffine(matrix)), type);
- }
-
- /**
- * Creates a coordinate operation from a math transform.
- *
- * @param name The identifier for the operation to be created.
- * @param sourceCRS The source coordinate reference system.
- * @param targetCRS The destination coordinate reference system.
- * @param transform The math transform.
- * @return A coordinate operation using the specified math transform.
- * @throws FactoryException if the operation can not be constructed.
- */
- private CoordinateOperation createFromMathTransform(final Identifier
name,
- final
CoordinateReferenceSystem sourceCRS,
- final
CoordinateReferenceSystem targetCRS,
- final MathTransform
transform)
- throws FactoryException
- {
- return
createFromMathTransform(Collections.singletonMap(CoordinateOperation.NAME_KEY,
name),
- sourceCRS, targetCRS, transform, null, SingleOperation.class);
+ final MathTransform transform =
factorySIS.getMathTransformFactory().createAffineTransform(matrix);
+ return createFromMathTransform(properties(name), sourceCRS, targetCRS,
transform, null, null);
}
/**
@@ -516,6 +549,11 @@ public class CoordinateOperationInferenc
* and a {@code MathTransform}, but that combination is not
forbidden. Since such practice is sometime
* convenient for the implementor, Apache SIS allows that.</div></li>
*
+ * <li>If the given {@code type} is null, then this method infers the
type from whether the given properties
+ * specify and accuracy or not. If those properties were created by
the {@link #properties(Identifier)}
+ * method, then the operation will be a {@link Transformation}
instance instead of {@link Conversion} if
+ * the {@code name} identifier was {@link #DATUM_SHIFT} or {@link
#ELLIPSOID_CHANGE}.</li>
+ *
* <li>If the given {@code method} is {@code null}, then infer an
operation method by inspecting the given transform.
* The transform needs to implement the {@link Parameterized}
interface in order to allow operation method discovery.</li>
*
@@ -528,16 +566,16 @@ public class CoordinateOperationInferenc
* @param targetCRS The destination coordinate reference system.
* @param transform The math transform.
* @param method The operation method, or {@code null} if unknown.
- * @param type The required super-class (e.g. <code>{@linkplain
Transformation}.class</code>).
+ * @param type {@code Conversion.class}, {@code
Transformation.class}, or {@code null} if unknown.
* @return A coordinate operation using the specified math transform.
- * @throws FactoryException if the operation can't be constructed.
+ * @throws FactoryException if the operation can not be created.
*/
private CoordinateOperation createFromMathTransform(final Map<String,?>
properties,
final
CoordinateReferenceSystem sourceCRS,
final
CoordinateReferenceSystem targetCRS,
final MathTransform
transform,
OperationMethod
method,
- final Class<? extends
CoordinateOperation> type)
+ Class<? extends
CoordinateOperation> type)
throws FactoryException
{
/*
@@ -556,21 +594,35 @@ public class CoordinateOperationInferenc
}
}
/*
+ * If the operation type was not explicitely specified, infers it from
whether an accuracy is specified
+ * or not. In principle, only transformations has an accuracy
property; conversions do not. This policy
+ * is applied by the properties(Identifier) method in this class.
+ */
+ if (type == null) {
+ type =
properties.containsKey(CoordinateOperation.COORDINATE_OPERATION_ACCURACY_KEY)
+ ? Transformation.class : Conversion.class;
+ }
+ /*
* The operation method is mandatory. If the user did not provided
one, we need to infer it ourselves.
* If we fail to infer an OperationMethod, let it to null - the
exception will be thrown by the factory.
*/
- if (method == null && transform instanceof Parameterized) {
- final ParameterDescriptorGroup descriptor = ((Parameterized)
transform).getParameterDescriptors();
- if (descriptor != null) {
- final Identifier name = descriptor.getName();
- if (name != null) {
- method = factory.getOperationMethod(name.getCode());
- }
- if (method == null) {
- method = factory.createOperationMethod(properties,
- sourceCRS.getCoordinateSystem().getDimension(),
- targetCRS.getCoordinateSystem().getDimension(),
- descriptor);
+ if (method == null) {
+ final Matrix matrix = MathTransforms.getMatrix(transform);
+ if (matrix != null) {
+ method = Affine.getProvider(transform.getSourceDimensions(),
transform.getTargetDimensions(), Matrices.isAffine(matrix));
+ } else if (transform instanceof Parameterized) {
+ final ParameterDescriptorGroup descriptor = ((Parameterized)
transform).getParameterDescriptors();
+ if (descriptor != null) {
+ final Identifier name = descriptor.getName();
+ if (name != null) {
+ method = factory.getOperationMethod(name.getCode());
+ }
+ if (method == null) {
+ method = factory.createOperationMethod(properties,
+ sourceCRS.getCoordinateSystem().getDimension(),
+ targetCRS.getCoordinateSystem().getDimension(),
+ descriptor);
+ }
}
}
}
@@ -632,56 +684,6 @@ public class CoordinateOperationInferenc
}
/**
- * Returns {@code true} if the Greenwich longitude of the {@code actual}
prime meridian is equals to the
- * Greenwich longitude of the {@code expected} prime meridian. The
comparison is performed in degrees.
- *
- * <p>A {@code null} argument is interpreted as "unknown prime meridian".
Consequently this method
- * unconditionally returns {@code false} if one or both arguments is
{@code null}.</p>
- *
- * @param expected The expected prime meridian, or {@code null}.
- * @param actual The actual prime meridian, or {@code null}.
- * @return {@code true} if both prime meridians have the same Greenwich
longitude.
- */
- private static boolean isGreenwichLongitudeEquals(final PrimeMeridian
expected, final PrimeMeridian actual) {
- if (expected == null || actual == null) {
- return false; // See method javadoc.
- }
- if (expected == actual) {
- return true;
- }
- final double diff =
ReferencingUtilities.getGreenwichLongitude(expected, NonSI.DEGREE_ANGLE)
- - ReferencingUtilities.getGreenwichLongitude(actual,
NonSI.DEGREE_ANGLE);
- return Math.abs(diff) <= Formulas.ANGULAR_TOLERANCE;
- }
-
- /**
- * Returns an affine transform between two coordinate systems. Only units
and axis order
- * (e.g. transforming from (NORTH,WEST) to (EAST,NORTH)) are taken in
account.
- *
- * <p>This method delegates to {@link
CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)}
- * and wraps the unchecked exceptions into the checked {@link
OperationNotFoundException}.</p>
- *
- * @param sourceCS the source coordinate system.
- * @param targetCS the target coordinate system.
- * @return The transformation from {@code sourceCS} to {@code targetCS} as
an affine transform.
- * @throws OperationNotFoundException if the affine transform can't be
constructed.
- *
- * @see CoordinateSystems#swapAndScaleAxes(CoordinateSystem,
CoordinateSystem)
- */
- private static Matrix swapAndScaleAxes(final CoordinateSystem sourceCS,
- final CoordinateSystem targetCS)
- throws OperationNotFoundException
- {
- try {
- return CoordinateSystems.swapAndScaleAxes(sourceCS,targetCS);
- } catch (IllegalArgumentException | ConversionException exception) {
- throw new OperationNotFoundException(notFoundMessage(sourceCS,
targetCS), exception);
- }
- // No attempt to catch ClassCastException since such
- // exception would indicates a programming error.
- }
-
- /**
* Returns the specified identifier in a map to be given to coordinate
operation constructors.
* In the special case where the {@code name} identifier is {@link
#DATUM_SHIFT} or {@link #ELLIPSOID_CHANGE},
* the map will contains extra informations like positional accuracy.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -162,6 +162,18 @@ public class DefaultCoordinateOperationF
}
/**
+ * Returns the Apache SIS implementation of math transform factory.
+ * This method is used only when we need SIS-specific methods.
+ */
+ final DefaultMathTransformFactory getDefaultMathTransformFactory() {
+ MathTransformFactory factory = getMathTransformFactory();
+ if (factory instanceof DefaultMathTransformFactory) {
+ return (DefaultMathTransformFactory) factory;
+ }
+ return DefaultFactories.forBuildin(MathTransformFactory.class,
DefaultMathTransformFactory.class);
+ }
+
+ /**
* Returns the operation method of the given name. The given argument
shall be either a method
* {@linkplain DefaultOperationMethod#getName() name} (e.g.
<cite>"Transverse Mercator"</cite>)
* or one of its {@linkplain DefaultOperationMethod#getIdentifiers()
identifiers} (e.g. {@code "EPSG:9807"}).
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -35,7 +35,6 @@ import org.apache.sis.internal.util.Cons
import org.apache.sis.metadata.iso.ImmutableIdentifier;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
-import org.apache.sis.referencing.cs.AbstractCS;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.CoordinateSystems;
import org.apache.sis.referencing.operation.DefaultOperationMethod;
@@ -170,20 +169,20 @@ abstract class CoordinateSystemTransform
if (source instanceof CartesianCS) {
if (target instanceof SphericalCS) {
kernel = CartesianToSpherical.INSTANCE;
- } else if (target instanceof CylindricalCS) {
- passthrough = 1;
- kernel = CartesianToPolar.INSTANCE;
} else if (target instanceof PolarCS) {
kernel = CartesianToPolar.INSTANCE;
+ } else if (target instanceof CylindricalCS) {
+ kernel = CartesianToPolar.INSTANCE;
+ passthrough = 1;
}
} else if (target instanceof CartesianCS) {
if (source instanceof SphericalCS) {
kernel = SphericalToCartesian.INSTANCE;
- } else if (source instanceof CylindricalCS) {
- passthrough = 1;
- kernel = PolarToCartesian.INSTANCE;
} else if (source instanceof PolarCS) {
kernel = PolarToCartesian.INSTANCE;
+ } else if (source instanceof CylindricalCS) {
+ kernel = PolarToCartesian.INSTANCE;
+ passthrough = 1;
}
}
Exception cause = null;
@@ -196,8 +195,14 @@ abstract class CoordinateSystemTransform
final MathTransform tr = (passthrough == 0)
? kernel.completeTransform(factory)
: kernel.passthrough(factory);
- return factory.createConcatenatedTransform(normalize(factory,
source, false),
- factory.createConcatenatedTransform(tr,
normalize(factory, target, true)));
+ final MathTransform before = factory.createAffineTransform(
+ CoordinateSystems.swapAndScaleAxes(source,
+ CoordinateSystems.replaceAxes(source,
AxesConvention.NORMALIZED)));
+ final MathTransform after = factory.createAffineTransform(
+ CoordinateSystems.swapAndScaleAxes(
+ CoordinateSystems.replaceAxes(target,
AxesConvention.NORMALIZED), target));
+ return factory.createConcatenatedTransform(before,
+ factory.createConcatenatedTransform(tr, after));
}
} catch (IllegalArgumentException | ConversionException e) {
cause = e;
@@ -206,20 +211,4 @@ abstract class CoordinateSystemTransform
WKTUtilities.toType(CoordinateSystem.class, source.getClass()),
WKTUtilities.toType(CoordinateSystem.class,
target.getClass())), cause);
}
-
- /**
- * Returns the conversion between the given coordinate system and its
normalized form.
- */
- private static MathTransform normalize(final MathTransformFactory factory,
final CoordinateSystem cs,
- final boolean inverse) throws FactoryException, ConversionException
- {
- AbstractCS source = AbstractCS.castOrCopy(cs);
- AbstractCS target = source.forConvention(AxesConvention.NORMALIZED);
- if (inverse) {
- AbstractCS tmp = source;
- source = target;
- target = tmp;
- }
- return
factory.createAffineTransform(CoordinateSystems.swapAndScaleAxes(source,
target));
- }
}
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -965,7 +965,7 @@ public class DefaultMathTransformFactory
/**
* Given a transform between normalized spaces,
- * create a transform taking in account axis directions and units of
measurement.
+ * creates a transform taking in account axis directions and units of
measurement.
* This method {@linkplain #createConcatenatedTransform concatenates} the
given parameterized transform
* with any other transform required for performing units changes and
ordinates swapping.
*
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -37,7 +37,7 @@ import static org.apache.sis.test.Assert
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.4
- * @version 0.6
+ * @version 0.7
* @module
*/
public final strictfp class BursaWolfParametersTest extends TestCase {
@@ -55,7 +55,7 @@ public final strictfp class BursaWolfPar
bursaWolf.tZ = 4.5;
bursaWolf.rZ = 0.554;
bursaWolf.dS = 0.219;
- bursaWolf.verify();
+ bursaWolf.verify(PrimeMeridianMock.GREENWICH);
assertFalse("isIdentity", bursaWolf.isIdentity());
assertFalse("isTranslation", bursaWolf.isTranslation());
return bursaWolf;
@@ -75,7 +75,7 @@ public final strictfp class BursaWolfPar
bursaWolf.rY = 0.1503;
bursaWolf.rZ = 0.3898;
bursaWolf.dS = -0.3143;
- bursaWolf.verify();
+ bursaWolf.verify(PrimeMeridianMock.GREENWICH);
assertFalse("isIdentity", bursaWolf.isIdentity());
assertFalse("isTranslation", bursaWolf.isTranslation());
return bursaWolf;
@@ -91,7 +91,7 @@ public final strictfp class BursaWolfPar
bursaWolf.tX = -168;
bursaWolf.tY = -60;
bursaWolf.tZ = 320;
- bursaWolf.verify();
+ bursaWolf.verify(PrimeMeridianMock.GREENWICH);
assertFalse("isIdentity", bursaWolf.isIdentity());
assertTrue ("isTranslation", bursaWolf.isTranslation());
return bursaWolf;
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -589,6 +589,11 @@ public final class Errors extends Indexe
public static final short MismatchedParameterDescriptor_1 = 146;
/**
+ * Expected the “{0}” prime meridian but found “{1}”.
+ */
+ public static final short MismatchedPrimeMeridian_2 = 220;
+
+ /**
* Mismatched type for “{0}” property.
*/
public static final short MismatchedPropertyType_1 = 154;
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] Mon Mar 21 13:49:07 2016
@@ -128,6 +128,7 @@ MismatchedDimension_3 = Argu
MismatchedGridGeometry_2 = The grid geometry must be the same for
\u201c{0}\u201d and \u201c{1}\u201d.
MismatchedMatrixSize_4 = Mismatched matrix sizes: expected
{0}\u00d7{1} but got {2}\u00d7{3}.
MismatchedParameterDescriptor_1 = Mismatched descriptor for \u201c{0}\u201d
parameter.
+MismatchedPrimeMeridian_2 = Expected the \u201c{0}\u201d prime
meridian but found \u201c{1}\u201d.
MismatchedPropertyType_1 = Mismatched type for \u201c{0}\u201d
property.
MismatchedTransformDimension_3 = The transform has {2}
{0,choice,0#source|1#target} dimension{2,choice,1#|2#s}, while {1} was expected.
MismatchedValueClass_3 = Class of \u201c{0}\u201d values is
\u2018{2}\u2019, but the requested type is \u2018{1}\u2019.
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] Mon Mar 21 13:49:07 2016
@@ -125,6 +125,7 @@ MismatchedDimension_3 = L\u2
MismatchedGridGeometry_2 = La g\u00e9om\u00e9trie de la grille doit
\u00eatre la m\u00eame pour \u00ab\u202f{0}\u202f\u00bb et
\u00ab\u202f{1}\u202f\u00bb.
MismatchedMatrixSize_4 = Une matrice de taille de {0}\u00d7{1}
\u00e9tait attendue mais la matrice donn\u00e9e est de taille {2}\u00d7{3}.
MismatchedParameterDescriptor_1 = Le descripteur du param\u00e8tre
\u00ab\u202f{0}\u202f\u00bb ne correspond pas.
+MismatchedPrimeMeridian_2 = Le m\u00e9ridien d\u2019origine
\u00ab\u202f{0}\u202f\u00bb \u00e9tait attendu, mais
\u00ab\u202f{1}\u202f\u00bb a \u00e9t\u00e9 trouv\u00e9.
MismatchedPropertyType_1 = Le type de la propri\u00e9t\u00e9
\u00ab\u202f{0}\u202f\u00bb ne correspond pas.
MismatchedTransformDimension_3 = La {0,choice,0#source|1#destination} de la
transformation a {2} dimension{2,choice,1#|2#s}, alors qu\u2019on en attendait
{1}.
MismatchedValueClass_3 = Les valeurs de \u00ab\u202f{0}\u202f\u00bb
sont de la classe \u2018{2}\u2019, alors que le type demand\u00e9 \u00e9tait
\u2018{1}\u2019.
Modified:
sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java
[UTF-8] Mon Mar 21 13:49:07 2016
@@ -20,6 +20,7 @@ import java.util.Queue;
import java.util.LinkedList;
import java.util.ConcurrentModificationException;
import java.util.logging.Filter;
+import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;
@@ -127,7 +128,9 @@ public final strictfp class LoggingWatch
*/
@Override
public final boolean isLoggable(final LogRecord record) {
- messages.add(formatter.formatMessage(record));
+ if (record.getLevel().intValue() >= Level.INFO.intValue()) {
+ messages.add(formatter.formatMessage(record));
+ }
return TestCase.VERBOSE;
}