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 edabd5aee9 Avoid a rounding error which caused the creation of
unnecessary concatenated transforms.
edabd5aee9 is described below
commit edabd5aee986f857dbf77ba9fb134eebdf184a52
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon Jul 11 11:23:20 2022 +0200
Avoid a rounding error which caused the creation of unnecessary
concatenated transforms.
---
.../internal/referencing/WraparoundApplicator.java | 27 +++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundApplicator.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundApplicator.java
index 9f6a5c60d6..943f853273 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundApplicator.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundApplicator.java
@@ -29,6 +29,7 @@ import org.opengis.referencing.operation.TransformException;
import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.referencing.operation.transform.WraparoundTransform;
import org.apache.sis.util.collection.BackingStoreException;
+import org.apache.sis.internal.util.Numerics;
import org.apache.sis.measure.Longitude;
import org.apache.sis.measure.Units;
@@ -38,7 +39,7 @@ import org.apache.sis.measure.Units;
* Each {@code WraparoundTransform} instance should be used only once.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
* @since 1.1
* @module
*/
@@ -165,10 +166,34 @@ public final class WraparoundApplicator {
// Some `DirectPosition` implementations compute coordinates only
when first needed.
throw e.unwrapOrRethrow(TransformException.class);
}
+ /*
+ * If the two medians are very close to each other, make them equal.
It simplifies the chain of operations.
+ * This code applies an arbitrary threshold for avoiding the effect of
rounding errors, because `create(…)`
+ * will use the difference between those two values.
+ */
+ final double max = Math.max(Math.abs(sm), Math.abs(m));
+ if (Math.abs(sm - m) < max * Numerics.COMPARISON_THRESHOLD) {
+ // Arbitrarily take the value closest to an integer.
+ final int n = Math.getExponent(max);
+ if (error(sm, n) <= error(m, n)) {
+ m = sm;
+ } else {
+ sm = m;
+ }
+ }
final MathTransform wraparound =
WraparoundTransform.create(tr.getTargetDimensions(), wraparoundDimension,
period, sm, m);
return MathTransforms.concatenate(tr, wraparound);
}
+ /**
+ * Returns an arbitrary measurement of the error of given value.
+ * We use this measurement for arbitrarily taking the value closest to an
integer.
+ */
+ private static double error(double m, final int n) {
+ m = Math.scalb(m, 6 - n); // 6 is an arbitrary extra
accuracy to keep for comparison.
+ return Math.abs(m - Math.rint(m));
+ }
+
/**
* Returns the range (maximum - minimum) of axis in specified dimension if
it has wraparound meaning,
* or {@link Double#NaN} otherwise. This method implements a fallback for
longitude axis if it does