You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2019/01/26 17:18:58 UTC
[sis] 04/04: Move more methods in order to improve a bit the
encapsulation.
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 6c47bc29fda3476be5cd0f0c7ef2856e50bd4c59
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sat Jan 26 17:22:12 2019 +0100
Move more methods in order to improve a bit the encapsulation.
---
.../java/org/apache/sis/internal/netcdf/Axis.java | 113 ++++++++++++++++++++-
.../java/org/apache/sis/internal/netcdf/Grid.java | 94 ++++-------------
.../apache/sis/storage/netcdf/MetadataReader.java | 4 +-
3 files changed, 133 insertions(+), 78 deletions(-)
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
index 5736831..d015017 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
@@ -38,10 +38,12 @@ import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.iso.Types;
+import org.apache.sis.util.ArraysExt;
import org.apache.sis.measure.Longitude;
import org.apache.sis.measure.Latitude;
import org.apache.sis.measure.Units;
import org.apache.sis.math.Vector;
+import org.apache.sis.referencing.operation.builder.LocalizationGridBuilder;
import ucar.nc2.constants.CDM;
import ucar.nc2.constants.CF;
@@ -115,7 +117,7 @@ public final class Axis extends NamedElement implements Comparable<Axis> {
* equals to the {@link #sourceDimensions} length. For each element, {@code sourceSizes[i]} shall
* be equals to the number of grid cells in the grid dimension at index {@code sourceDimensions[i]}.
*/
- public final int[] sourceSizes;
+ final int[] sourceSizes;
/**
* Values of coordinates on this axis for given grid indices. This variables is often one-dimensional,
@@ -204,6 +206,71 @@ public final class Axis extends NamedElement implements Comparable<Axis> {
}
/**
+ * Swaps the two first source dimensions if needed for making the fastest varying dimension first.
+ * This is a helper method for {@link Grid#getAxes()} invoked after all axes of a grid have been created.
+ * This method needs to know other axes in order to avoid collision.
+ *
+ * @param axes previously created axes.
+ * @param count number of elements to consider in the {@code axes} array.
+ * @throws IOException if an I/O operation was necessary but failed.
+ * @throws DataStoreException if a logical error occurred.
+ * @throws ArithmeticException if the size of an axis exceeds {@link Integer#MAX_VALUE}, or other overflow occurs.
+ *
+ * @see #getDimension()
+ */
+ final void mainDimensionFirst(final Axis[] axes, final int count) throws IOException, DataStoreException {
+ final int d0 = sourceDimensions[0];
+ final int d1 = sourceDimensions[1];
+ boolean s = false;
+ for (int i=0; i<count; i++) {
+ final int[] other = axes[i].sourceDimensions;
+ if (other.length != 0) {
+ final int first = other[0];
+ if (first == d1) return; // Swapping would cause a collision.
+ s = (first == d0);
+ if (s) break; // Need swapping for avoiding collision.
+ }
+ }
+ if (!s) {
+ final int up0 = sourceSizes[0];
+ final int up1 = sourceSizes[1];
+ final int mid0 = up0 / 2;
+ final int mid1 = up1 / 2;
+ final double inc0 = (coordinates.coordinateForAxis( 0, mid1) -
+ coordinates.coordinateForAxis(up0-1, mid1)) / up0;
+ final double inc1 = (coordinates.coordinateForAxis(mid0, 0) -
+ coordinates.coordinateForAxis(mid0, up1-1)) / up1;
+ if (!(Math.abs(inc1) > Math.abs(inc0))) {
+ return;
+ }
+ }
+ ArraysExt.swap(sourceSizes, 0, 1);
+ ArraysExt.swap(sourceDimensions, 0, 1);
+ }
+
+ /**
+ * Returns the number of dimension of the localization grid used by this axis.
+ * This method returns 2 if this axis if backed by a localization grid having 2 or more dimensions.
+ * In the netCDF UCAR library, such axes are handled by a {@link ucar.nc2.dataset.CoordinateAxis2D}.
+ *
+ * @return number of dimension of the localization grid used by this axis.
+ */
+ public final int getDimension() {
+ return sourceDimensions.length;
+ }
+
+ /**
+ * Returns the number of cells in the first dimension of the localization grid used by this axis.
+ * If the localization grid has more than one dimension ({@link #getDimension()} {@literal > 1}),
+ * then all additional dimensions are ignored. The first dimension should be the main one.
+ *
+ * @return number of cells in the first (main) dimension of the localization grid.
+ */
+ public final int getLength() {
+ return (sourceSizes.length != 0) ? sourceSizes[0] : 0;
+ }
+
+ /**
* Returns the name of this axis.
*
* @return the name of this element.
@@ -381,7 +448,7 @@ public final class Axis extends NamedElement implements Comparable<Axis> {
final boolean trySetTransform(final Matrix gridToCRS, final int lastSrcDim, final int tgtDim,
final List<MathTransform> nonLinears) throws IOException, DataStoreException
{
-main: switch (sourceDimensions.length) {
+main: switch (getDimension()) {
/*
* Defined as a matter of principle, but should never happen.
*/
@@ -456,4 +523,46 @@ main: switch (sourceDimensions.length) {
nonLinears.add(null);
return false;
}
+
+ /**
+ * Tries to create a two-dimensional localization grid using this axis and the given axis.
+ * This method is invoked as a fallback when {@link #trySetTransform(Matrix, int, int, List)}
+ * could not set coefficients in the matrix of an affine transform.
+ *
+ * @param other the other axis to use for creating a localization grid.
+ * @return the localization grid, or {@code null} if none can be built.
+ * @throws IOException if an error occurred while reading the data.
+ * @throws DataStoreException if a logical error occurred.
+ */
+ final LocalizationGridBuilder createLocalizationGrid(final Axis other) throws IOException, DataStoreException {
+ if (other.getDimension() == 2) {
+ final int d1 = sourceDimensions[0];
+ final int d2 = sourceDimensions[1];
+ final int o1 = other.sourceDimensions[0];
+ final int o2 = other.sourceDimensions[1];
+ if ((o1 == d1 && o2 == d2) || (o1 == d2 && o2 == d1)) {
+ /*
+ * Found two axes for the same set of dimensions, which implies that they have
+ * the same shape (width and height).
+ */
+ final int width = sourceSizes[0];
+ final int height = sourceSizes[1];
+ final LocalizationGridBuilder grid = new LocalizationGridBuilder(width, height);
+ final Vector v1 = coordinates.read();
+ final Vector v2 = other.coordinates.read();
+ final double[] target = new double[2];
+ int index = 0;
+ for (int y=0; y<height; y++) {
+ for (int x=0; x<width; x++) {
+ target[0] = v1.doubleValue(index);
+ target[1] = v2.doubleValue(index);
+ grid.setControlPoint(x, y, target);
+ index++;
+ }
+ }
+ return grid;
+ }
+ }
+ return null;
+ }
}
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
index 3c8f52f..49ce6b7 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
@@ -40,8 +40,6 @@ import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.coverage.grid.IllegalGridGeometryException;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.util.NullArgumentException;
-import org.apache.sis.util.ArraysExt;
-import org.apache.sis.math.Vector;
/**
@@ -159,12 +157,11 @@ public abstract class Grid extends NamedElement {
int i = 0, deferred = workspace.length;
for (final Axis axis : axes) {
// Put one-dimensional axes first, all other axes last.
- workspace[axis.sourceDimensions.length <= 1 ? i++ : --deferred] = axis;
+ workspace[axis.getDimension() <= 1 ? i++ : --deferred] = axis;
}
deferred = workspace.length; // Will become index of the first axis whose examination has been deferred.
while (i < workspace.length) { // Start the loop at the first n-dimensional axis (n > 1).
final Axis axis = workspace[i];
- final int[] sourceDimensions = axis.sourceDimensions;
/*
* If an axis has a "wraparound" range (for example a longitude axis where the next value after +180°
* may be -180°), we will examine it last. The reason is that if a wraparound occurs in the middle of
@@ -175,35 +172,10 @@ public abstract class Grid extends NamedElement {
if (i < deferred && axis.isWraparound()) {
System.arraycopy(workspace, i+1, workspace, i, --deferred - i);
workspace[deferred] = axis;
- continue; // Continue the loop without incrementing 'i'.
- }
- Boolean swap = null;
- for (int p=0; p<i; p++) {
- final int[] other = workspace[p].sourceDimensions;
- if (other.length != 0) {
- final int first = other[0];
- if (first == sourceDimensions[1]) {swap=false; break;} // Swapping would cause a collision.
- if (first == sourceDimensions[0]) {swap=true; break;} // Need swapping for avoiding collision.
- }
- }
- final int[] sourceSizes = axis.sourceSizes;
- if (swap == null) {
- final int up0 = sourceSizes[0];
- final int up1 = sourceSizes[1];
- final int mid0 = up0 / 2;
- final int mid1 = up1 / 2;
- final Variable coordinates = axis.coordinates;
- final double inc0 = (coordinates.coordinateForAxis( 0, mid1) -
- coordinates.coordinateForAxis(up0-1, mid1)) / up0;
- final double inc1 = (coordinates.coordinateForAxis(mid0, 0) -
- coordinates.coordinateForAxis(mid0, up1-1)) / up1;
- swap = Math.abs(inc1) > Math.abs(inc0);
- }
- if (swap) {
- ArraysExt.swap(sourceSizes, 0, 1);
- ArraysExt.swap(sourceDimensions, 0, 1);
+ } else {
+ axis.mainDimensionFirst(workspace, i);
+ i++;
}
- i++;
}
}
return axes;
@@ -269,7 +241,7 @@ public abstract class Grid extends NamedElement {
case 0: break;
}
for (final Axis axis : axes) {
- if (axis.sourceDimensions.length == 1) {
+ if (axis.getDimension() == 1) {
final DimensionNameType name;
if (AxisDirections.isVertical(axis.direction)) {
name = DimensionNameType.VERTICAL;
@@ -349,51 +321,25 @@ findFree: for (int srcDim : axis.sourceDimensions) {
for (int i=0; i<nonLinears.size(); i++) { // Length of 'nonLinears' may change in this loop.
if (nonLinears.get(i) == null) {
final Axis axis = axes[deferred[i]];
- if (axis.sourceDimensions.length == 2) {
- final int d1 = axis.sourceDimensions[0];
- final int d2 = axis.sourceDimensions[1];
+ if (axis.getDimension() == 2) {
for (int j=i; ++j < nonLinears.size();) {
if (nonLinears.get(j) == null) {
- final Axis other = axes[deferred[j]];
- if (other.sourceDimensions.length == 2) {
- final int o1 = other.sourceDimensions[0];
- final int o2 = other.sourceDimensions[1];
- if ((o1 == d1 && o2 == d2) || (o1 == d2 && o2 == d1)) {
+ final int srcDim = sourceDimensions[i];
+ final int otherDim = sourceDimensions[j];
+ if (Math.abs(srcDim - otherDim) == 1) { // Need axes at consecutive source dimensions.
+ final LocalizationGridBuilder grid = axis.createLocalizationGrid(axes[deferred[j]]);
+ if (grid != null) {
/*
- * Found two axes for the same set of dimensions, which implies that they have
- * the same shape (width and height). In current implementation, we also need
- * those axes to be at consecutive source dimensions.
+ * Replace the first transform by the two-dimensional localization grid and
+ * remove the other transform. Removals need to be done in arrays too.
*/
- final int srcDim = sourceDimensions[i];
- final int otherDim = sourceDimensions[j];
- if (Math.abs(srcDim - otherDim) == 1) {
- final int width = axis.sourceSizes[0];
- final int height = axis.sourceSizes[1];
- final LocalizationGridBuilder grid = new LocalizationGridBuilder(width, height);
- final Vector v1 = axis.coordinates.read();
- final Vector v2 = other.coordinates.read();
- final double[] target = new double[2];
- int index = 0;
- for (int y=0; y<height; y++) {
- for (int x=0; x<width; x++) {
- target[0] = v1.doubleValue(index);
- target[1] = v2.doubleValue(index);
- grid.setControlPoint(x, y, target);
- index++;
- }
- }
- /*
- * Replace the first transform by the two-dimensional localization grid and
- * remove the other transform. Removals need to be done in arrays too.
- */
- nonLinears.set(i, grid.create(factory));
- nonLinears.remove(j);
- final int n = nonLinears.size() - j;
- System.arraycopy(deferred, j+1, deferred, j, n);
- System.arraycopy(sourceDimensions, j+1, sourceDimensions, j, n);
- if (otherDim < srcDim) {
- sourceDimensions[i] = otherDim;
- }
+ nonLinears.set(i, grid.create(factory));
+ nonLinears.remove(j);
+ final int n = nonLinears.size() - j;
+ System.arraycopy(deferred, j+1, deferred, j, n);
+ System.arraycopy(sourceDimensions, j+1, sourceDimensions, j, n);
+ if (otherDim < srcDim) {
+ sourceDimensions[i] = otherDim;
}
}
}
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
index 950819f..2127810 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
@@ -724,8 +724,8 @@ split: while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
* the 'sourceDimensions' and 'sourceSizes' arrays are for the grid dimension which is most closely
* oriented toward the axis direction.
*/
- if (axis.sourceSizes.length >= 1) {
- setAxisLength(dim, axis.sourceSizes[0]);
+ if (axis.getDimension() >= 1) {
+ setAxisLength(dim, axis.getLength());
}
final AttributeNames.Dimension attributeNames;
switch (axis.abbreviation) {