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 634a39a70cebad149ff4c47687db3f46e2890a54
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Fri Feb 28 12:59:47 2025 +0100

    Vertical resolution was fetched from the old dimension when z is not the 
third axis.
---
 .../sis/storage/geotiff/writer/GeoEncoder.java     | 52 +++++++++++++++++++---
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
index a0d4db0378..7bdd7ef79d 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
@@ -40,6 +40,7 @@ import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.EllipsoidalCS;
+import org.opengis.referencing.cs.VerticalCS;
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.datum.PrimeMeridian;
 import org.opengis.referencing.datum.GeodeticDatum;
@@ -77,6 +78,7 @@ import org.apache.sis.storage.geotiff.base.GeoCodes;
 import org.apache.sis.storage.geotiff.base.Resources;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.math.MathFunctions;
 import org.apache.sis.pending.jdk.JDK15;
 
 
@@ -294,30 +296,66 @@ public final class GeoEncoder {
         final CoordinateReferenceSystem fullCRS = 
grid.getCoordinateReferenceSystem();
         final VerticalCRS vertical = CRS.getVerticalComponent(fullCRS, true);
         if (vertical != null) {
-            final CoordinateSystem cs = vertical.getCoordinateSystem();
+            final VerticalCS cs = vertical.getCoordinateSystem();
             final int verticalDimension = 
AxisDirections.indexOfColinear(fullCRS.getCoordinateSystem(), cs);
-            if (verticalDimension >= 0 && Arrays.binarySearch(dimensions, 
verticalDimension) < 0) {
+            if (verticalDimension >= 0 && isNotHorizontal(verticalDimension, 
dimensions)) {
                 writeCRS(vertical);
                 axisDirections = Arrays.copyOf(axisDirections, 
BIDIMENSIONAL+1);
                 axisDirections[BIDIMENSIONAL] = cs.getAxis(0).getDirection();
                 if (gridToCRS != null) {
                     gridToCRS = Matrices.resizeAffine(gridToCRS, MATRIX_SIZE, 
MATRIX_SIZE);
                     Matrix more = grid.getLinearGridToCRS(anchor).getMatrix();
+                    final int translationColumn = more.getNumCol() - 1;
                     for (int i=0; i<MATRIX_SIZE; i++) {
                         final int s;
                         switch (i) {
-                            default:            s = dimensions[i];        
break;    // Shear from horizontal dimensions.
-                            case BIDIMENSIONAL: s = verticalDimension;    
break;    // Scale from vertical dimension.
-                            case MATRIX_SIZE-1: s = more.getNumCol() - 1; 
break;    // Translation.
+                            default:            s = dimensions[i];     break;  
  // Shear from horizontal dimensions.
+                            case BIDIMENSIONAL: s = verticalDimension; break;  
  // Scale from vertical dimension.
+                            case MATRIX_SIZE-1: s = translationColumn; break;  
  // Translation.
                         }
-                        // Copy the rows of the third dimension.
-                        gridToCRS.setElement(BIDIMENSIONAL, i, 
more.getElement(BIDIMENSIONAL, s));
+                        /*
+                         * Copy the matrix row for the third dimension. Each 
column in the target matrix come from
+                         * one column of the source matrix, except the scale 
factor of the vertical dimension when
+                         * the number of dimensions is greater than 3. In the 
latter case, the scale will be set
+                         * to the magnitude of all non-horizontal columns. 
This is a safety for the fact that we
+                         * do not know for sure in which column is the scale 
factor.
+                         */
+                        double value = more.getElement(verticalDimension, s);
+                        if (s == verticalDimension && translationColumn > 
BIDIMENSIONAL + 1) {
+                            final var values = new double[translationColumn - 
BIDIMENSIONAL];
+                            for (int skip=0, j=0; j < values.length; j++) {
+                                if (isNotHorizontal(j, dimensions)) {
+                                    values[j] = 
more.getElement(verticalDimension, j + skip);
+                                } else {
+                                    skip++;
+                                }
+                            }
+                            value = 
Math.copySign(MathFunctions.magnitude(values), Arrays.stream(values).sum());
+                        }
+                        gridToCRS.setElement(BIDIMENSIONAL, i, value);
                     }
                 }
             }
         }
     }
 
+    /**
+     * Returns whether the given dimension is <em>not</em> one of the 
horizontal dimensions.
+     * This length of the horizontal array should be {@value #BIDIMENSIONAL}.
+     *
+     * @param  dimension   the dimension to test.
+     * @param  horizontal  the horizontal dimensions.
+     * @return whether the given dimension is <em>not</em> horizontal.
+     */
+    private static boolean isNotHorizontal(final int dimension, final int[] 
horizontal) {
+        for (int d : horizontal) {
+            if (d == dimension) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * Writes the first keys (model type, raster type, citation).
      * This method shall be the first write operation, before to write any 
other keys.

Reply via email to