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 b1182eb2d140e9802bad7283160ec3c661f59e3a Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Feb 17 11:56:06 2022 +0100 Fix ClassCastException when showing a GeoTIFF image with anchor points. --- .../apache/sis/internal/referencing/RTreeNode.java | 26 +++++++++++++--------- .../transform/SpecializableTransform.java | 11 ++++----- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/RTreeNode.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/RTreeNode.java index 2ba0e4d..0c28dcb 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/RTreeNode.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/RTreeNode.java @@ -194,14 +194,17 @@ detach: for (RTreeNode next; node != null; node = next) { } /** - * Finishes the construction of the tree. This methods sets the CRS of all nodes to a common value. - * An exception is thrown if incompatible CRS are found. This method does not verify the number of - * dimensions; this check should have been done by the caller. + * Finishes the construction of the tree. This method should be invoked only on the instance + * on which {@link #addNode(RTreeNode)} has been invoked. It performs the following tasks: * - * <p>This method should be invoked only on the instance on which {@link #addNode(RTreeNode)} has been - * invoked.</p> + * <ol> + * <li>Verify that all nodes have the same CRS or null CRS. An exception is thrown if incompatible CRS are found. + * This method does not verify the number of dimensions; this check should have been done by the caller.</li> + * <li>Set the CRS of all nodes to the common value found in previous step.</li> + * <li>Ensure that the tree has a single root, by creating a synthetic parent if necessary.</li> + * </ol> * - * @return the root of the tree (may be {@code this}). + * @return the root of the tree, which is {@code this} if this node has no sibling. */ public final RTreeNode finish() { final Uniformizer action = new Uniformizer(); @@ -214,8 +217,9 @@ detach: for (RTreeNode next; node != null; node = next) { } /* * If there is more than one node, create a synthetic parent containing them all. - * We do not need to traverse all node for this task; only the immediate children - * of the new parent. + * We do not need to traverse all nodes for this task; only the immediate children + * of the new parent. The purpose of the synthetic parent is to have a single root + * (i.e. no sibling). */ parent = new RTreeNode(this); parent.firstChild = this; @@ -263,12 +267,12 @@ detach: for (RTreeNode next; node != null; node = next) { * to give to this method the most recently used node.</p> * * @param node any node in the tree. Should be node most likely to contain the position. - * @param pos the position of the node to locate. - * @return the smallest node containing the given position. + * @param pos the position of the node to locate, or {@code null} if none. + * @return the smallest node containing the given position, or {@code null} if none. */ public static RTreeNode locate(RTreeNode node, final DirectPosition pos) { RTreeNode skip = null; // For avoiding to invoke `contains(pos)` twice on the same mode. - do { + if (node != null) do { if (node.contains(pos)) { /* * Before to return the node we just found, check if a child contains the point. diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java index 9567bfc..25cd5b8 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java @@ -42,7 +42,7 @@ import org.apache.sis.util.Utilities; * The lower and upper values of given envelopes are inclusive. * * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @version 1.2 * * @see MathTransforms#specialize(MathTransform, Map) * @@ -132,6 +132,7 @@ class SpecializableTransform extends AbstractMathTransform implements Serializab /** * Domains where specialized transforms are valid. This is the root of an R-Tree. + * May be {@code null} if there is no R-Tree, in which case {@link #global} should be used instead. */ private final RTreeNode domains; @@ -255,7 +256,7 @@ class SpecializableTransform extends AbstractMathTransform implements Serializab */ private MathTransform forDomain(final DirectPosition pos) { final RTreeNode domain = RTreeNode.locate(domains, pos); - return (domain != null) ? ((SubArea) domain).transform : global; + return (domain instanceof SubArea) ? ((SubArea) domain).transform : global; } /** @@ -343,7 +344,7 @@ class SpecializableTransform extends AbstractMathTransform implements Serializab if (--numPts <= 0) break; next = SubArea.locate(domain, src); // Cheaper check compared to the case where domain is null. } while (next == domain); - domain = (SubArea) next; + domain = (next instanceof SubArea) ? (SubArea) next : null; } final int num = (src.offset - srcOff) / srcInc; int dstLow = dstOff; @@ -460,7 +461,7 @@ class SpecializableTransform extends AbstractMathTransform implements Serializab */ @Override protected final int computeHashCode() { - return super.computeHashCode() + 7*global.hashCode() ^ domains.hashCode(); + return super.computeHashCode() + 7*global.hashCode() ^ Objects.hashCode(domains); } /** @@ -652,7 +653,7 @@ class SpecializableTransform extends AbstractMathTransform implements Serializab } while (next == domain); // Continue until we find a change of specialized transform. num = (dst.offset - dstOff) / dstInc; // Number of points to transform. transform.apply(domain.inverse, srcOff, dstOff, num); - domain = (SubArea) next; + domain = (next instanceof SubArea) ? (SubArea) next : null; srcOff += srcInc * num; dstOff = dst.offset; } while (domain != null);