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 2021/03/22 15:05:25 UTC
[sis] branch geoapi-4.0 updated: Refactor `LinearTransformBuilder.approximate(…)` implementation in a separated class. Change method signature and add a `GridGeometry.linearize(…)` method.
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 07257ce Refactor `LinearTransformBuilder.approximate(…)` implementation in a separated class. Change method signature and add a `GridGeometry.linearize(…)` method.
07257ce is described below
commit 07257cef751d7698e3a3c15b63882273ff54ebe8
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Mon Mar 22 14:26:44 2021 +0100
Refactor `LinearTransformBuilder.approximate(…)` implementation in a separated class.
Change method signature and add a `GridGeometry.linearize(…)` method.
---
.../org/apache/sis/coverage/grid/GridExtent.java | 6 +-
.../org/apache/sis/coverage/grid/GridGeometry.java | 52 +++++++
.../operation/builder/LinearTransformBuilder.java | 31 ++--
.../referencing/operation/builder/Linearizer.java | 158 +++++++++++++++++++++
.../operation/builder/ResidualGrid.java | 57 --------
.../operation/builder/LinearizerTest.java | 72 ++++++++++
.../builder/LocalizationGridBuilderTest.java | 38 +----
.../sis/test/suite/ReferencingTestSuite.java | 1 +
8 files changed, 299 insertions(+), 116 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
index 293a864..0e4b37c 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
@@ -916,8 +916,9 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
/**
* Transforms this grid extent to a "real world" envelope using the given transform.
* The transform shall map <em>cell corner</em> to real world coordinates.
+ * This method does not set the envelope coordinate reference system.
*
- * @param cornerToCRS a transform from <em>cell corners</em> to real world coordinates.
+ * @param cornerToCRS a transform from <em>cell corners</em> to real world coordinates, or {@code null} if none.
* @param gridToCRS the transform specified by the user. May be the same as {@code cornerToCRS}.
* If different, then this is assumed to map cell centers instead of cell corners.
* @param fallback bounds to use if some values still NaN, or {@code null} if none.
@@ -936,6 +937,9 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
if (high != Long.MAX_VALUE) high++; // Make the coordinate exclusive before cast.
envelope.setRange(i, coordinates[i], high); // Possible loss of precision in cast to `double` type.
}
+ if (cornerToCRS == null) {
+ return envelope;
+ }
envelope = Envelopes.transform(cornerToCRS, envelope);
if (envelope.isEmpty()) try {
/*
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
index 833740f..768ab7e 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
@@ -51,6 +51,7 @@ 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.PassThroughTransform;
+import org.apache.sis.referencing.operation.builder.LinearTransformBuilder;
import org.apache.sis.internal.referencing.DirectPositionView;
import org.apache.sis.internal.referencing.TemporalAccessor;
import org.apache.sis.internal.referencing.AxisDirections;
@@ -1290,6 +1291,57 @@ public class GridGeometry implements LenientComparable, Serializable {
}
/**
+ * Creates a grid geometry with a linear approximation of the <cite>grid to CRS</cite> transform.
+ * The approximation is computed by <cite>Least Mean Squares</cite> method: the affine transform
+ * coefficients are chosen in way making the average value of (<var>position</var> − <var>linear
+ * approximation of position</var>)² as small as possible for all cells in this grid geometry.
+ * If the <cite>grid to CRS</cite> transform of this grid geometry is already linear, then this
+ * method returns {@code this}.
+ *
+ * @param forceLowerToZero whether to force lower grid coordinates to (0,0,…).
+ * @return a grid geometry with a linear approximation of the <cite>grid to CRS</cite> transform.
+ * @throws TransformException if some cell coordinates can not be computed.
+ *
+ * @see LinearTransformBuilder#approximate(MathTransform, Envelope)
+ * @see GridExtent#startsAtZero()
+ */
+ public GridGeometry linearize(final boolean forceLowerToZero) throws TransformException {
+ if (nonLinears != 0 && extent != null) try {
+ GeneralEnvelope domain = extent.toCRS(null, null, null);
+ MathTransform approximate = LinearTransformBuilder.approximate(gridToCRS, domain);
+ MathTransform gridToGrid = MathTransforms.concatenate(gridToCRS, approximate.inverse());
+ domain = Envelopes.transform(gridToGrid, domain);
+ final int dimension = domain.getDimension();
+ final long[] coordinates = new long[dimension * 2];
+ final double[] shift = new double[dimension];
+ for (int i=0; i<dimension; i++) {
+ long low = Math.round(domain.getMinimum(i));
+ long high = Math.round(domain.getMaximum(i));
+ high = Math.max(low, Math.decrementExact(high));
+ if (forceLowerToZero) {
+ high = Math.subtractExact(high, low);
+ shift[i] = low;
+ } else {
+ coordinates[i] = low;
+ }
+ coordinates[i + dimension] = high;
+ }
+ approximate = MathTransforms.concatenate(MathTransforms.translation(shift), approximate);
+ if (!approximate.equals(gridToCRS)) {
+ return new GridGeometry(new GridExtent(extent, coordinates), PixelInCell.CELL_CENTER,
+ approximate, envelope.getCoordinateReferenceSystem());
+ }
+ } catch (FactoryException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof TransformException) {
+ throw (TransformException) cause;
+ }
+ throw new TransformException(e);
+ }
+ return this;
+ }
+
+ /**
* Creates a transform from cell coordinates in this grid to cell coordinates in the given grid.
* The returned transform handles change of Coordinate Reference System and wraparound axes
* (e.g. longitude axis crossing the ±180° meridian) if applicable.
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 c70b38a..fc78b3e 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
@@ -228,7 +228,7 @@ public class LinearTransformBuilder extends TransformBuilder {
* @since 0.8
*/
public LinearTransformBuilder(int... gridSize) {
- ArgumentChecks.ensureNonNull("gridSize", gridSize);
+ ArgumentChecks.ensureNonEmpty("gridSize", gridSize, 1, Integer.MAX_VALUE, false);
if (gridSize.length == 0) {
this.gridSize = null;
this.gridLength = 0;
@@ -250,36 +250,25 @@ public class LinearTransformBuilder extends TransformBuilder {
/**
* Returns a linear approximation of the given transform for the specified domain.
- * The source positions are all integer coordinates in a rectangle from (0, 0, …) inclusive
- * to {@code gridSize} exclusive. The target positions are the results of transforming all
- * source coordinates with the given {@code gridToCRS} transform.
- * This method is equivalent to the following code, but potentially more efficient:
- *
- * {@preformat java
- * val builder = new LinearTransformBuilder(gridSize);
- * builder.setControlPoints(gridToCRS);
- * return builder.create(null);
- * }
+ * The source positions are integer coordinates included in the given envelope.
+ * The target positions are the results of transforming source coordinates with
+ * the given {@code gridToCRS} transform.
*
* @param gridToCRS the transform from source coordinates (grid indices) to target coordinates.
- * @param gridSize the upper values (exclusive) of source coordinates.
+ * @param domain domain of integer source coordinates for which to get a linear approximation.
* @return a linear approximation of given transform for the specified domain.
* @throws FactoryException if the transform approximation can not be computed.
*
* @see #setControlPoints(MathTransform)
+ * @see org.apache.sis.coverage.grid.GridGeometry#linearize(boolean)
*
* @since 1.1
*/
- public static LinearTransform approximate(final MathTransform gridToCRS, final int... gridSize) throws FactoryException {
+ public static LinearTransform approximate(final MathTransform gridToCRS, final Envelope domain) throws FactoryException {
ArgumentChecks.ensureNonNull("gridToCRS", gridToCRS);
+ ArgumentChecks.ensureNonNull("domain", domain);
try {
- final LinearTransform mt = ResidualGrid.approximate(gridToCRS, gridSize);
- if (mt != null) {
- return mt;
- }
- final LinearTransformBuilder builder = new LinearTransformBuilder(gridSize);
- builder.setControlPoints(gridToCRS);
- return builder.create(null);
+ return (LinearTransform) Linearizer.approximate(gridToCRS, domain);
} catch (TransformException e) {
throw new FactoryException(e);
}
@@ -579,7 +568,7 @@ search: for (int j=numPoints; --j >= 0;) {
* @param gridToCRS the transform from source coordinates (grid indices) to target coordinates.
* @throws TransformException if a coordinate value can not be transformed.
*
- * @see #approximate(MathTransform, int...)
+ * @see #approximate(MathTransform, Envelope)
*
* @since 1.1
*/
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/Linearizer.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/Linearizer.java
new file mode 100644
index 0000000..2379791
--- /dev/null
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/Linearizer.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.operation.builder;
+
+import java.util.Iterator;
+import org.opengis.geometry.Envelope;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.geometry.Envelopes;
+import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.referencing.datum.DatumShiftGrid;
+import org.apache.sis.referencing.operation.transform.InterpolatedTransform;
+import org.apache.sis.referencing.operation.transform.LinearTransform;
+import org.apache.sis.referencing.operation.transform.MathTransforms;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * Computes a linear approximation of a {@link MathTransform}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ * @since 1.1
+ * @module
+ */
+final class Linearizer {
+ /**
+ * Do not allow instantiation of this class.
+ */
+ private Linearizer() {
+ }
+
+ /**
+ * Returns a linear approximation of the given transform for the specified domain.
+ * The source positions are integer coordinates included in the given envelope.
+ * The target positions are the results of transforming source coordinates with
+ * the given {@code gridToCRS} transform.
+ *
+ * <p>If a linear approximation can be extracted from the given transform, this method returns
+ * that approximation directly. This method tries to avoid expensive calculation; it searches
+ * for transforms than can be processed easily.</p>
+ *
+ * @param gridToCRS the transform from source coordinates (grid indices) to target coordinates.
+ * @param domain domain of integer source coordinates for which to get a linear approximation.
+ * @return a linear approximation of given transform for the specified domain.
+ * @throws FactoryException if the transform approximation can not be computed.
+ */
+ static MathTransform approximate(final MathTransform gridToCRS, final Envelope domain)
+ throws TransformException, FactoryException
+ {
+ if (domain.getDimension() != ResidualGrid.SOURCE_DIMENSION) {
+ return compute(gridToCRS, domain, null);
+ }
+ MathTransform result = null;
+ final Iterator<MathTransform> it = MathTransforms.getSteps(gridToCRS).iterator();
+ while (it.hasNext()) {
+ MathTransform step = it.next();
+ if (step instanceof LinearTransform) {
+ result = (result != null) ? MathTransforms.concatenate(result, step) : step;
+ } else if (step instanceof InterpolatedTransform) {
+ /*
+ * Non-linear transform found. If it is backed by a `ResidualGrid` and the specified domain
+ * contains the full `ResidualGrid` domain, then we consider that `step` is approximated by
+ * an identity transform. Otherwise this method can not process `gridToCRS`.
+ */
+ final DatumShiftGrid<?,?> grid = ((InterpolatedTransform) step).getShiftGrid();
+ MathTransform sourceToGrid = grid.getCoordinateToGrid();
+ if (result != null) {
+ sourceToGrid = MathTransforms.concatenate(result, sourceToGrid);
+ }
+ final GeneralEnvelope gd = Envelopes.transform(sourceToGrid, domain);
+checkResidual: if (grid instanceof ResidualGrid) {
+ /*
+ * Verifiy pixel coordinates as if they were rounded to nearest integers and assuming that
+ * the envelope maximal values are inclusive (this is why we subtract 1.5 instead of 0.5).
+ * If the specified envelope is inside the `ResidualGrid` domain, then the approximation
+ * should be computed using a subset of the points included in this grid.
+ */
+ for (int i=0; i<ResidualGrid.SOURCE_DIMENSION; i++) {
+ if (gd.getMinimum(i) >= 0.5 || gd.getMaximum(i) <= grid.getGridSize(i) - 1.5) {
+ break checkResidual;
+ }
+ }
+ /*
+ * The `step` transform matches criterion. Consider that we can approximate this step by the
+ * identity transform. If we applied `LinearTransformBuilder` on this step, we should indeed
+ * get a result close to identity transform because of the way that `LocalizationGridBuilder`
+ * computes `ResidualGrid`: if we invoke `LinearTransformBuilder.setControlPoints(gridToCRS)`
+ * we would reconstitute the same set of points than the one that `LocalizationGridBuilder`
+ * used for computing a linear approximation before to compute the `ResidualGrid`.
+ */
+ continue;
+ }
+ /*
+ * The given domain does not use all grid points, or the grid is not a type that we known to be
+ * close to identity. We have to compute the approximation. But instead of computing it on all
+ * points in source domain, we use only the point in the grid. It can be much less computation.
+ */
+ while (it.hasNext()) {
+ // Complete the transform will all remaining steps.
+ step = MathTransforms.concatenate(step, it.next());
+ }
+ return MathTransforms.concatenate(sourceToGrid, compute(step, gd, grid));
+ } else {
+ /*
+ * Non-linear transform of unknown type. There is no optimization we can do.
+ */
+ return compute(gridToCRS, domain, null);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Computes a linear approximation of the given transform. This is an expensive fallback used only
+ * when we could not find an existing value by inspection of {@code gridToCRS} transform steps.
+ */
+ private static MathTransform compute(final MathTransform gridToCRS, final Envelope domain,
+ final DatumShiftGrid<?,?> grid) throws TransformException, FactoryException
+ {
+ final int[] size = new int[domain.getDimension()];
+ final double[] shift = new double[size.length];
+ for (int i=0; i<size.length; i++) {
+ double lower = Math.rint(domain.getMinimum(i));
+ double upper = Math.rint(domain.getMaximum(i));
+ if (grid != null) {
+ final double h = grid.getGridSize(i);
+ if (upper > h) upper = h;
+ if (lower < 0) lower = 0;
+ }
+ final double span = upper - lower;
+ if (!(span <= Integer.MAX_VALUE)) { // Use `!` for catching NaN.
+ throw new ArithmeticException(Errors.format(Errors.Keys.IntegerOverflow_1, Integer.SIZE));
+ }
+ shift[i] = lower;
+ size [i] = (int) span;
+ }
+ final LinearTransformBuilder builder = new LinearTransformBuilder(size);
+ final LinearTransform translate = MathTransforms.translation(shift);
+ builder.setControlPoints(MathTransforms.concatenate(translate, gridToCRS));
+ return MathTransforms.concatenate(translate.inverse(), builder.create(null));
+ }
+}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ResidualGrid.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ResidualGrid.java
index bce70ef..b74069b 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ResidualGrid.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ResidualGrid.java
@@ -22,19 +22,14 @@ import javax.measure.quantity.Dimensionless;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.referencing.operation.Matrix;
-import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.parameter.Parameters;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.referencing.datum.DatumShiftGrid;
import org.apache.sis.referencing.operation.matrix.MatrixSIS;
-import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.referencing.operation.transform.LinearTransform;
import org.apache.sis.referencing.operation.transform.ContextualParameters;
-import org.apache.sis.referencing.operation.transform.InterpolatedTransform;
import org.apache.sis.internal.referencing.WKTUtilities;
-import org.apache.sis.geometry.GeneralEnvelope;
-import org.apache.sis.geometry.Envelopes;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.internal.util.Numerics;
import org.apache.sis.io.wkt.FormattableObject;
@@ -42,7 +37,6 @@ import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.math.Statistics;
import org.apache.sis.math.Vector;
import org.apache.sis.measure.Units;
-import org.apache.sis.util.ArraysExt;
/**
@@ -395,57 +389,6 @@ final class ResidualGrid extends DatumShiftGrid<Dimensionless,Dimensionless> {
}
/**
- * If a linear approximation can be extracted from the given transform, returns that approximation.
- * The approximation applies to source coordinates in the range 0 to {@code size[i]} for each source
- * dimension <var>i</var>.
- *
- * <p>This method does not perform expansive calculation; it searches only for transforms than can
- * be processed easily. This method is defined in this class because it checks for transformations
- * backed by {@link ResidualGrid} instances.</p>
- *
- * @param size upper coordinate values of the source domain for which to get a linear approximation.
- * @return the linear approximation of given transform, or {@code null} if none readily available.
- */
- static LinearTransform approximate(final MathTransform gridToCRS, final int[] size) throws TransformException {
- if (size.length != SOURCE_DIMENSION) {
- return null;
- }
- MathTransform result = null;
- for (final MathTransform step : MathTransforms.getSteps(gridToCRS)) {
- if (step instanceof LinearTransform) {
- if (result == null) {
- result = step;
- } else {
- result = MathTransforms.concatenate(result, step);
- }
- } else {
- /*
- * Non-linear transform found. If it is backed by a `ResidualGrid` and the specified domain
- * contains the full `ResidualGrid` domain, then we consider that `step` is approximated by
- * an identity transform. Otherwise this method can not process `gridToCRS`.
- */
- if (step instanceof InterpolatedTransform) {
- final DatumShiftGrid<?,?> grid = ((InterpolatedTransform) step).getShiftGrid();
- if (grid instanceof ResidualGrid) {
- GeneralEnvelope bounds = new GeneralEnvelope(new double[size.length], ArraysExt.copyAsDoubles(size));
- if (result != null) {
- bounds = Envelopes.transform(result, bounds);
- }
- for (int i=0; i<size.length; i++) {
- if (bounds.getMinimum(i) > 0 || bounds.getMaximum(i) < grid.getGridSize(i)) {
- return null;
- }
- }
- continue;
- }
- }
- return null;
- }
- }
- return (LinearTransform) result;
- }
-
- /**
* Returns {@code true} if the given object is a grid containing the same data than this grid.
*/
@Override
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearizerTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearizerTest.java
new file mode 100644
index 0000000..d3db170
--- /dev/null
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearizerTest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.operation.builder;
+
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.referencing.operation.matrix.Matrix3;
+import org.apache.sis.referencing.operation.transform.LinearTransform;
+import org.apache.sis.referencing.operation.HardCodedConversions;
+import org.apache.sis.geometry.Envelope2D;
+import org.apache.sis.test.DependsOn;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests {@link Linearizer}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ * @since 1.1
+ * @module
+ */
+@DependsOn(LocalizationGridBuilderTest.class)
+public final strictfp class LinearizerTest {
+ /**
+ * Tests {@link LinearTransformBuilder#approximate(MathTransform, Envelope)} on a transform created by
+ * {@link LocalizationGridBuilder}. We verify that the {@link Linearizer#approximate(MathTransform,
+ * Envelope)} short path is executed.
+ *
+ * @throws TransformException if an error occurred while computing test points.
+ * @throws FactoryException if an error occurred while computing the localization grid.
+ *
+ * @see LinearTransformBuilderTest#testSetPointsFromTransform()
+ */
+ @Test
+ public void testApproximate() throws TransformException, FactoryException {
+ // Same set of points than `LinearTransformBuilderTest.testSetPointsFromTransform()`.
+ final LinearTransformBuilder points = new LinearTransformBuilder(3, 5);
+ points.setControlPoints(HardCodedConversions.mercator().getConversionFromBase().getMathTransform());
+
+ // Non-linear transform producing the same values than the set of points;
+ final LocalizationGridBuilder builder = new LocalizationGridBuilder(points);
+ final MathTransform transform = builder.create(null);
+ assertFalse(transform instanceof LinearTransform);
+
+ // Linear approximation by Least Square Root method.
+ final LinearTransform linear = LinearTransformBuilder.approximate(transform, new Envelope2D(null, 0, 0, 3, 5));
+ org.opengis.test.Assert.assertMatrixEquals("linear",
+ new Matrix3(111319, 0, 0,
+ 0, 110662, -62,
+ 0, 0, 1), linear.getMatrix(), 0.5);
+
+ assertSame("Should have extracted the existing instance instead of computing a new one.", points.create(null), linear);
+ }
+}
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilderTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilderTest.java
index 0d10365..803cefa 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilderTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilderTest.java
@@ -19,13 +19,9 @@ package org.apache.sis.referencing.operation.builder;
import java.awt.geom.Point2D;
import java.awt.geom.AffineTransform;
import org.opengis.util.FactoryException;
-import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.opengis.test.referencing.TransformTestCase;
-import org.apache.sis.referencing.operation.HardCodedConversions;
-import org.apache.sis.referencing.operation.transform.LinearTransform;
import org.apache.sis.geometry.Envelope2D;
-import org.apache.sis.referencing.operation.matrix.Matrix3;
import org.apache.sis.test.DependsOn;
import org.junit.Test;
@@ -36,7 +32,7 @@ import static org.apache.sis.test.ReferencingAssert.*;
* Tests {@link LocalizationGridBuilder}.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.0
* @since 0.8
* @module
*/
@@ -150,36 +146,4 @@ public final strictfp class LocalizationGridBuilderTest extends TransformTestCas
assertArrayEquals(new double[] {-8.5, -123.7}, builder.getRow(1, 2).doubleValues(), STRICT);
assertArrayEquals(new double[] {-21.7, -26.2, -123.7}, builder.getColumn(1, 1).doubleValues(), STRICT);
}
-
- /**
- * Tests {@link LinearTransformBuilder#approximate(MathTransform, int...)} on a transform created by
- * {@link LocalizationGridBuilder}. We verify that the {@link ResidualGrid#approximate(MathTransform, int[])}
- * short path is executed.
- *
- * @throws TransformException if an error occurred while computing test points.
- * @throws FactoryException if an error occurred while computing the localization grid.
- *
- * @see LinearTransformBuilderTest#testSetPointsFromTransform()
- */
- @Test
- public void testApproximate() throws TransformException, FactoryException {
- // Same set of points than `LinearTransformBuilderTest.testSetPointsFromTransform()`.
- final int[] gridSize = {3, 5};
- final LinearTransformBuilder points = new LinearTransformBuilder(gridSize);
- points.setControlPoints(HardCodedConversions.mercator().getConversionFromBase().getMathTransform());
-
- // Non-linear transform producing the same values than the set of points;
- final LocalizationGridBuilder builder = new LocalizationGridBuilder(points);
- transform = builder.create(null);
- assertFalse(transform instanceof LinearTransform);
-
- // Linear approximation by Least Square Root method.
- final LinearTransform linear = LinearTransformBuilder.approximate(transform, gridSize);
- org.opengis.test.Assert.assertMatrixEquals("linear",
- new Matrix3(111319, 0, 0,
- 0, 110662, -62,
- 0, 0, 1), linear.getMatrix(), 0.5);
-
- assertSame("Should have extracted the existing instance instead of computing a new one.", points.create(null), linear);
- }
}
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
index cd66eb8..d3165e7 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
@@ -264,6 +264,7 @@ import org.junit.BeforeClass;
org.apache.sis.referencing.operation.builder.ResidualGridTest.class,
org.apache.sis.referencing.operation.builder.LinearTransformBuilderTest.class,
org.apache.sis.referencing.operation.builder.LocalizationGridBuilderTest.class,
+ org.apache.sis.referencing.operation.builder.LinearizerTest.class,
// GeoAPI conformance test suite.
org.apache.sis.referencing.geoapi.AuthorityFactoryTest.class,