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 2019/03/11 19:30:11 UTC
[sis] branch geoapi-4.0 updated: The non-linear transform
concatenated by LocalizationGridBuilder needs to take in account axis
swapping.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new aca9be6 The non-linear transform concatenated by LocalizationGridBuilder needs to take in account axis swapping.
aca9be6 is described below
commit aca9be685b338e5dc9e1d4cb065074e78ee75780
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Mon Mar 11 20:29:42 2019 +0100
The non-linear transform concatenated by LocalizationGridBuilder needs to take in account axis swapping.
---
.../operation/builder/LinearTransformBuilder.java | 16 ++++++-------
.../operation/builder/LocalizationGridBuilder.java | 18 ++++++++++++--
.../operation/builder/ProjectedTransformTry.java | 28 ++++++++++++++++------
.../builder/LinearTransformBuilderTest.java | 10 ++++----
4 files changed, 50 insertions(+), 22 deletions(-)
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
index c1492e2..df447ae 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
@@ -1121,8 +1121,9 @@ search: for (int j=domain(); --j >= 0;) {
* {@linkplain #correlation() correlation} coefficients. It may be none.
*
* <p>The linearizers are specified as {@link MathTransform}s from current target coordinates to other spaces
- * where <cite>sources to new targets</cite> transforms may be more linear. The keys in the map are arbitrary
- * identifiers used in {@link #toString()} for debugging purpose.
+ * where <cite>sources to new targets</cite> transforms may be more linear.
+ * Keys in the map are arbitrary identifiers used in {@link #toString()} for debugging purpose.
+ * Values in the map are non-{@link LinearTransform} (linear transforms are not forbidden, but are useless for this process).
* The {@code dimensions} argument specifies which target dimensions to project and can be null or omitted
* if the projections shall be applied on all target coordinates. It is possible to invoke this method many
* times with different {@code dimensions} argument values.</p>
@@ -1148,10 +1149,7 @@ search: for (int j=domain(); --j >= 0;) {
linearizers = new ArrayList<>();
}
for (final Map.Entry<String,MathTransform> entry : projections.entrySet()) {
- ProjectedTransformTry t = new ProjectedTransformTry(entry.getKey(), entry.getValue(), dimensions, tgtDim);
- if (!t.projection.isIdentity()) {
- linearizers.add(t);
- }
+ linearizers.add(new ProjectedTransformTry(entry.getKey(), entry.getValue(), dimensions, tgtDim));
}
}
@@ -1328,7 +1326,7 @@ search: for (int j=domain(); --j >= 0;) {
}
/**
- * If all target coordinates have been projected to another space, returns the projection applied.
+ * If target coordinates have been projected to another space, returns that projection.
* This method returns a non-empty value only if all the following conditions are met:
*
* <ol>
@@ -1340,13 +1338,15 @@ search: for (int j=domain(); --j >= 0;) {
*
* If this method returns a non-empty value, then the envelope returned by {@link #getTargetEnvelope()}
* and all control points returned by {@link #getControlPoint(int[])} are projected by this transform.
+ * The returned transform includes axes swapping specified by the {@code dimensions} argument given to
+ * <code>{@linkplain #addLinearizers(Map, int...) addLinearizers}(…, dimensions)</code>.
*
* @return the projection applied on target coordinates before to compute a linear transform.
*
* @since 1.0
*/
public Optional<MathTransform> linearizer() {
- return (appliedLinearizer != null) ? Optional.of(appliedLinearizer.projection) : Optional.empty();
+ return (appliedLinearizer != null) ? Optional.of(appliedLinearizer.projection()) : Optional.empty();
}
/**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
index 6a919d0..86a9304 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
@@ -664,7 +664,21 @@ public class LocalizationGridBuilder extends TransformBuilder {
/**
* Returns statistics of differences between values calculated by the given transform and actual values.
* The given math transform is typically the transform computed by {@link #create(MathTransformFactory)},
- * but not necessarily.
+ * but not necessarily. The returned statistics are:
+ *
+ * <ol class="verbose">
+ * <li>One {@code Statistics} instance for each target dimension, containing statistics about the differences between
+ * coordinates computed by the given transform and expected coordinates. For each (<var>i</var>,<var>j</var>) indices
+ * in this grid, the indices are transformed by a call to {@code mt.transform(…)} and the result is compared with the
+ * coordinates given by <code>{@linkplain #getControlPoint(int, int) getControlPoint}(i,j)</code>.
+ * Those statistics are identified by labels like “P → x” and “P → y” where <var>P</var> stands for pixel coordinates.</li>
+ * <li>One {@code Statistics} instance for each source dimension, containing statistics about the differences between
+ * coordinates computed by the <em>inverse</em> of the transform and expected coordinates.
+ * For each (<var>x</var>,<var>y</var>) control point in this grid, the points are transformed by a call
+ * to {@code mt.inverse().transform(…)} and the result is compared with the pixel indices of that point.
+ * Those statistics are identified by labels like “i ← P′” and “j ← P′” where <var>P′</var> stands for
+ * the control point.</li>
+ * </ol>
*
* @param mt the transform to test.
* @return statistics of difference between computed values and expected values for each target dimension.
@@ -741,7 +755,7 @@ public class LocalizationGridBuilder extends TransformBuilder {
* <li>Number of points.</li>
* <li>Linearizers and their correlation coefficients (if available).</li>
* <li>The linear component of the transform.</li>
- * <li>Error statistics.</li>
+ * <li>Error statistics, as documented in the {@link #error(MathTransform)} method.</li>
* </ul>
*
* The string representation may change in any future version.
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java
index 92f01ba..4be4ecd 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java
@@ -28,7 +28,10 @@ import org.apache.sis.internal.referencing.Resources;
import org.apache.sis.io.TableAppender;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.Exceptions;
+import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.referencing.operation.transform.MathTransforms;
/**
@@ -66,15 +69,17 @@ final class ProjectedTransformTry implements Comparable<ProjectedTransformTry> {
private static final int BUFFER_CAPACITY = 512;
/**
- * A name by witch this projection attempt is identified.
+ * A name by witch this projection attempt is identified, or {@code null} for the identity transform.
*/
private String name;
/**
* A conversion from a non-linear grid (typically with longitude and latitude values) to
* something that may be more linear (typically, but not necessarily, a map projection).
+ *
+ * @see #projection()
*/
- final MathTransform projection;
+ private final MathTransform projection;
/**
* Maps {@link #projection} dimensions to {@link LinearTransformBuilder} target dimensions.
@@ -123,6 +128,8 @@ final class ProjectedTransformTry implements Comparable<ProjectedTransformTry> {
* @param expectedDimension number of {@link LinearTransformBuilder} target dimensions.
*/
ProjectedTransformTry(final String name, final MathTransform projection, final int[] dimensions, int expectedDimension) {
+ ArgumentChecks.ensureNonNull("name", name);
+ ArgumentChecks.ensureNonNull("projection", projection);
this.name = name;
this.projection = projection;
this.dimensions = dimensions;
@@ -143,14 +150,22 @@ final class ProjectedTransformTry implements Comparable<ProjectedTransformTry> {
}
/**
- * Returns the name of this object, or {@code null} if unspecified.
- * This is used only for formatting error messages.
+ * Returns the name of this object, or {@code null} if this is the identity transform created by
+ * {@link #ProjectedTransformTry(float)}. Should never be {@code null} for name returned to user.
*/
final String name() {
return name;
}
/**
+ * Returns the projection, taking in account axis swapping if {@link #dimensions} is not an arithmetic progression.
+ */
+ final MathTransform projection() {
+ MathTransform mt = MathTransforms.linear(Matrices.createDimensionSelect(dimensions.length, dimensions));
+ return MathTransforms.concatenate(mt, projection);
+ }
+
+ /**
* Transforms target coordinates of a localization grid. The {@code coordinates} argument is the value
* of {@link LinearTransformBuilder#targets}, without clone (this method will only read those arrays).
* Only arrays at indices given by {@link #dimensions} will be read; the other arrays will be ignored.
@@ -306,13 +321,12 @@ final class ProjectedTransformTry implements Comparable<ProjectedTransformTry> {
*
* @param table the table where to write a row.
* @param nf format to use for writing coefficients, or {@code null} if not yet created.
- * @param locale the locale to use if a number format must be created.
+ * @param locale the locale to use for messages or if a number format must be created.
* @return format used for writing coefficients, or {@code null}.
*/
final NumberFormat summarize(final TableAppender table, NumberFormat nf, final Locale locale) {
if (name == null) {
- final short key = (projection == null) ? Vocabulary.Keys.Identity : Vocabulary.Keys.Unnamed;
- name = Vocabulary.getResources(locale).getString(key);
+ name = Vocabulary.getResources(locale).getString(Vocabulary.Keys.Identity);
}
table.append(name).nextColumn();
String message = "";
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
index 582eaa1..868ce37 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
@@ -430,12 +430,12 @@ public final strictfp class LinearTransformBuilderTest extends TestCase {
builder.setControlPoint(source, target);
}
}
- final NonLinearTransform x2y3 = new NonLinearTransform();
- final NonLinearTransform x3y2 = new NonLinearTransform();
- builder.addLinearizers(Collections.singletonMap("x² y³", x2y3));
- builder.addLinearizers(Collections.singletonMap("x³ y²", x3y2), 1, 0);
+ final NonLinearTransform tr = new NonLinearTransform();
+ builder.addLinearizers(Collections.singletonMap("x² y³", tr));
+ builder.addLinearizers(Collections.singletonMap("x³ y²", tr), 1, 0);
final Matrix m = builder.create(null).getMatrix();
- assertSame("linearizer", x3y2, builder.linearizer().get());
+ assertEquals("linearizer", "x³ y²", builder.linearizerID());
+ assertNotSame("linearizer", tr, builder.linearizer().get()); // Not same because axes should have been swapped.
assertMatrixEquals("linear",
new Matrix3(2, 0, 3,
0, 1, 1,