sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 02/04: Try to be a little bit stricter on the check about whether a ResamplingGrid tile is close enough to a linear transform.
Date Sun, 05 Apr 2020 20:31:57 GMT
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

commit 19602071b5ad0357a8f9eecca7aac72128e024f7
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Sun Apr 5 17:17:39 2020 +0200

    Try to be a little bit stricter on the check about whether a ResamplingGrid tile is close
enough to a linear transform.
---
 .../java/org/apache/sis/image/ResamplingGrid.java  | 35 ++++++++++++++++++----
 .../org/apache/sis/image/ResamplingGridTest.java   |  9 +++---
 2 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/ResamplingGrid.java b/core/sis-feature/src/main/java/org/apache/sis/image/ResamplingGrid.java
index d1c83aa..399b5b0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/ResamplingGrid.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/ResamplingGrid.java
@@ -74,6 +74,8 @@ final class ResamplingGrid extends AbstractMathTransform2D {
      * The maximal error allowed, in pixel units.
      * This is the maximal difference allowed between a coordinate transformed
      * using the original transform and the same coordinate transformed using this grid.
+     * This maximum is honored on a best-effort basis; it may happen that for some pixels
+     * the error is slightly higher.
      */
     static final double TOLERANCE = 0.125;
 
@@ -209,6 +211,9 @@ final class ResamplingGrid extends AbstractMathTransform2D {
 
     /**
      * Creates a grid for the given domain of validity.
+     * The {@code toSourceCenter} argument is the transform used for computing the coordinate
values in the grid.
+     * The {@code toSourceCorner} argument is the transform used for computing derivatives
(Jacobian matrices)
+     * in order to determine when the grid as enough tiles.
      *
      * @param  toSourceCenter  transform from target grid center to source grid center.
      * @param  toSourceCorner  transform from target grid corner to source grid corner.
@@ -260,7 +265,7 @@ final class ResamplingGrid extends AbstractMathTransform2D {
          * Given f₁(x) = y₁ + (x − x₁)⋅m₁
          *   and f₃(x) = y₁ + (x − x₁)⋅m₃
          *
-         * then the error ε = f₃(x) − f₁(x) at location x−x₂ is (x₂−x₁)⋅(m₃−m₁).
+         * then the error ε = f₃(x) − f₁(x) at location x=x₂ is (x₂−x₁)⋅(m₃−m₁).
          * Given x₂ = (x₁+x₃)/2, we get ε = (x₃−x₁)/2 ⋅ (m₃−m₁).
          *
          * If we rearange the terms, we get:  (m₃−m₁) = 2⋅ε / (x₃−x₁).
@@ -271,7 +276,11 @@ final class ResamplingGrid extends AbstractMathTransform2D {
                 new Point2D.Double(2 * TOLERANCE / (xmax - xmin),
                                    2 * TOLERANCE / (ymax - ymin)),
                 xmin, xmax, ymin, ymax, upperLeft, upperRight, lowerLeft, lowerRight);
-        if (depth.width == 0 && depth.height == 0) {
+        /*
+         * At this point we got the `depth` argument we need for instantiating `ResamplingGrid`.
+         * The remaining code in this method is only a check for potential optimization.
+         */
+affine: if (depth.width == 0 && depth.height == 0) {
             /*
              * The transform is approximately affine. Compute the matrix coefficients using
the points projected
              * on the four borders of the domain, in order to get a kind of average coefficient
values. We don't
@@ -295,6 +304,22 @@ final class ResamplingGrid extends AbstractMathTransform2D {
                                                            p.getX(),     p.getY());
             tr.translate(-xcnt, -ycnt);
             roundIfAlmostInteger(tr);
+            /*
+             * Since the affine transform that we built is a kind of average computed from
bounds center,
+             * we need to compare with the four corners for making sure that its precision
is sufficient.
+             */
+            p = null;
+            for (int i=0; i<4; i++) {
+                point.x = (i & 1) == 0 ? xmin : xmax;
+                point.y = (i & 2) == 0 ? ymin : ymax;
+                p = tr.transform(point, p);
+                final Point2D expected = toSourceCenter.transform(point, point);
+                if (!(abs(p.getX() - expected.getX()) <= TOLERANCE &&
+                      abs(p.getY() - expected.getY()) <= TOLERANCE))
+                {
+                    break affine;
+                }
+            }
             return new AffineTransform2D(tr);
         }
         /*
@@ -481,10 +506,8 @@ final class ResamplingGrid extends AbstractMathTransform2D {
      * (resulting in smaller grids) inside the {@link #depth depth(…)} method.
      */
     private static boolean equals(final Matrix2 center, final Matrix2 corner, final Point2D.Double
tolerance) {
-        return abs(center.m00 - corner.m00) <= tolerance.x &&
-               abs(center.m01 - corner.m01) <= tolerance.x &&
-               abs(center.m10 - corner.m10) <= tolerance.y &&
-               abs(center.m11 - corner.m11) <= tolerance.y;
+        return abs(center.m00 - corner.m00) + abs(center.m01 - corner.m01) <= tolerance.x
&&
+               abs(center.m10 - corner.m10) + abs(center.m11 - corner.m11) <= tolerance.y;
     }
 
     /**
diff --git a/core/sis-feature/src/test/java/org/apache/sis/image/ResamplingGridTest.java b/core/sis-feature/src/test/java/org/apache/sis/image/ResamplingGridTest.java
index a4cf38c..0570eed 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/image/ResamplingGridTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/image/ResamplingGridTest.java
@@ -138,7 +138,7 @@ public final strictfp class ResamplingGridTest extends TestCase {
     private static MathTransform2D compare(final String title, final MathTransform projection,
final Rectangle2D domain)
             throws TransformException
     {
-        final Rectangle bounds = new Rectangle(10, 20, 800, 600);
+        final Rectangle bounds = new Rectangle(10, 20, 400, 150);
         final MathTransform2D reference = (MathTransform2D) MathTransforms.concatenate(
                 affine(bounds, domain), projection,
                 affine(Shapes2D.transform((MathTransform2D) projection, domain, null), bounds));
@@ -164,7 +164,8 @@ public final strictfp class ResamplingGridTest extends TestCase {
                 if (!(dx <= ResamplingGrid.TOLERANCE && dy <= ResamplingGrid.TOLERANCE))
{
                     fail("Error at (" + x + ',' + y + "): expected " +
                             Arrays.toString(expected) + " but got " +
-                            Arrays.toString(actual) + ". Error is (" + dx + ", " + dy + ')');
+                            Arrays.toString(actual) + ". Error is (" + dx + ", " + dy + ")."
+
+                            " Transform is:\n" + grid);
                 }
                 sx.accept(dx);
                 sy.accept(dy);
@@ -194,7 +195,7 @@ public final strictfp class ResamplingGridTest extends TestCase {
         assertInstanceOf("Expected a non-linear transform.", ResamplingGrid.class, tr);
         final ResamplingGrid grid = (ResamplingGrid) tr;
         assertEquals("The x dimension should be affine.",   1, grid.numXTiles);
-        assertEquals("The y dimension can not be affine.", 32, grid.numYTiles);     // Empirical
value.
+        assertEquals("The y dimension can not be affine.", 16, grid.numYTiles);     // Empirical
value.
     }
 
     /**
@@ -236,7 +237,7 @@ public final strictfp class ResamplingGridTest extends TestCase {
     @Test
     public void testLambertOnSmallArea() throws TransformException {
         final MathTransform projection = HardCodedConversions.lambert().getConversionFromBase().getMathTransform();
-        final Rectangle2D domain = new Rectangle2D.Double(-20, 50, 0.025, 0.05);
+        final Rectangle2D domain = new Rectangle2D.Double(-20, 50, 0.025, 0.025);
         final MathTransform2D tr = compare("Lambert (small area)", projection, domain);
         assertInstanceOf("Expected a linear transform.", AffineTransform2D.class, tr);
     }


Mime
View raw message