This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits 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 5107e0afa6 Fix an `IndexOutOfBoundsException` when the CRS component 
which is present in only the target CRS is not the last one.
5107e0afa6 is described below

commit 5107e0afa6afef69deed8fedf66a9b24ed6aab15
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Jul 24 17:50:41 2026 +0200

    Fix an `IndexOutOfBoundsException` when the CRS component which is present 
in only the target CRS is not the last one.
---
 .../operation/CoordinateOperationFinder.java       |  9 ++---
 .../referencing/operation/SubOperationInfo.java    | 40 ++++++++++++++++++++--
 2 files changed, 42 insertions(+), 7 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index 8b95682a0f..9b963d3e8d 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@ -925,6 +925,7 @@ public class CoordinateOperationFinder extends 
CoordinateOperationRegistry {
         }
         /*
          * At this point, a coordinate operation has been found for all 
components of the target CRS.
+         * That coordinate operation may be explicit (non-null) or implicit (a 
coordinate coordinate).
          * However, the CoordinateOperation.getSourceCRS() values are not 
necessarily in the same order
          * than in the `sourceComponents` list given to this method, and some 
dimensions may be dropped.
          * The matrix computed by sourceToSelected(…) gives us the 
rearrangement needed for the coordinate
@@ -934,9 +935,9 @@ public class CoordinateOperationFinder extends 
CoordinateOperationRegistry {
         final Matrix select = 
SubOperationInfo.sourceToSelected(sourceCRS.getCoordinateSystem().getDimension(),
 infos);
         /*
          * First, we need a CRS matching the above-cited rearrangement. That 
CRS will be named `stepSourceCRS`
-         * and its components will be named `stepComponents`. Then we will 
execute a loop in which each component
-         * is progressively (one by one) updated from a source component to a 
target component. A new step CRS is
-         * recreated each time, since it will be needed for each 
PassThroughOperation.
+         * and its components will be named `stepComponents`. Then we will 
execute a loop in which each
+         * component is progressively (one by one) updated from a source 
component to a target component.
+         * A new step CRS is recreated each time, since it will be needed for 
each PassThroughOperation.
          */
         CoordinateReferenceSystem stepSourceCRS;
         CoordinateOperation operation;
@@ -972,7 +973,7 @@ public class CoordinateOperationFinder extends 
CoordinateOperationRegistry {
              * Only after the loop finished, `stepTargetCRS` will become the 
complete target definition.
              */
             final CoordinateReferenceSystem stepTargetCRS;
-            stepComponents[info.targetComponentIndex] = target;
+            stepComponents[info.targetComponentIndex()] = target;
             if (i >= indexOfFinal) {
                 stepTargetCRS = targetCRS;              // If all remaining 
transforms are identity, we reached the final CRS.
             } else if (info.isIdentity()) {
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
index 3fb21d253b..764ba76372 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
@@ -31,6 +31,9 @@ import org.apache.sis.referencing.internal.Resources;
 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.measure.NumberRange;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.internal.shared.Strings;
 
 // Specific to the geoapi-4.0 branch:
 import org.apache.sis.referencing.legacy.DefaultImageCRS;
@@ -104,6 +107,9 @@ final class SubOperationInfo {
     /**
      * The first dimension (inclusive) and the last dimension (exclusive) 
where the
      * {@link SingleCRS} starts/ends in the full (usually compound) 
<abbr>CRS</abbr>.
+     * The source dimension may be equal to the target dimension if the 
component does
+     * not exist in the source <abbr>CRS</abbr>, in which case {@link 
#constantCoordinates}
+     * should be specified.
      *
      * @see #sourceToSelected(int, SubOperationInfo[])
      */
@@ -111,10 +117,13 @@ final class SubOperationInfo {
                       targetLowerDimension, targetUpperDimension;
 
     /**
-     * Index of this instance in the array of {@code SubOperationInfo} 
instances,
-     * before the reordering applied by {@link 
#getSourceCRS(SubOperationInfo[])}.
+     * Index of this instance in the array of {@code SubOperationInfo} 
instances.
+     * This is initially the index in the array returned by {@link 
#createSteps createSteps(…)},
+     * then is modified by the reordering applied by {@link 
#getSourceCRS(SubOperationInfo[])}.
+     *
+     * @see #targetComponentIndex()
      */
-    final int targetComponentIndex;
+    private int targetComponentIndex;
 
     /**
      * The component of the target <abbr>CRS</abbr> which is managed by this 
{@code SubOperationInfo}.
@@ -313,6 +322,10 @@ searchSrc:  while (sourceComponentIndex < 
sourceComponentIsUsed.length) {
             if (component.operation == null) {
                 System.arraycopy(selected, i+1, selected, i, last - i);
                 selected[last] = component;
+                component.targetComponentIndex = last;
+                for (int j = last; --j >= i;) {
+                    selected[j].targetComponentIndex--;
+                }
                 n--;
                 i--;
             }
@@ -396,6 +409,15 @@ searchSrc:  while (sourceComponentIndex < 
sourceComponentIsUsed.length) {
         return select;
     }
 
+    /**
+     * Returns the index of this instance in the array of {@code 
SubOperationInfo} instances.
+     * The returned value may differ depending on whether this method is 
invoked before or after
+     * {@link #getSourceCRS(SubOperationInfo[])}.
+     */
+    final int targetComponentIndex() {
+        return targetComponentIndex;
+    }
+
     /**
      * Returns {@code true} if the coordinate operation wrapped by this object 
is an identity transform.
      */
@@ -485,4 +507,16 @@ otherRow:           for (int j = last.getNumRow() - 1; --j 
>= 0;) {     // Ignor
     final boolean resultWasContextSensitive() {
         return constantCoordinates != null;
     }
+
+    /**
+     * Returns a string representation for debugging purposes.
+     */
+    @Override
+    public String toString() {
+        return Strings.toString(getClass(),
+                "index",  targetComponentIndex,
+                "type",   Classes.getShortClassName(targetComponent),
+                "source", new NumberRange<>(Integer.class, 
sourceLowerDimension, true, sourceUpperDimension, false),
+                "target", new NumberRange<>(Integer.class, 
targetLowerDimension, true, targetUpperDimension, false));
+    }
 }

Reply via email to