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.