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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new f34cf02b40 Make possible to invoke
`GridDerivation.subgrid(GridGeometry)` with an Area Of Interest having less
dimensions that the base, even if the extra dimensions are not a slice.
f34cf02b40 is described below
commit f34cf02b40463c09083a3593a369af67ac08a1b0
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Aug 1 19:05:56 2025 +0200
Make possible to invoke `GridDerivation.subgrid(GridGeometry)`
with an Area Of Interest having less dimensions that the base,
even if the extra dimensions are not a slice.
---
.../coverage/grid/CoordinateOperationFinder.java | 43 +++++++++++++++++--
.../apache/sis/coverage/grid/GridDerivation.java | 45 ++++++++++++++++++--
.../apache/sis/coverage/grid/SliceGeometry.java | 2 +-
.../sis/coverage/grid/GridDerivationTest.java | 49 ++++++++++++++++++++++
.../operation/CoordinateOperationContext.java | 28 +++++++++----
.../operation/CoordinateOperationFinder.java | 27 ++++++++++--
.../DefaultCoordinateOperationFactory.java | 31 ++++++++------
.../referencing/operation/SubOperationInfo.java | 13 ++++--
8 files changed, 202 insertions(+), 36 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/CoordinateOperationFinder.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/CoordinateOperationFinder.java
index ce1971a943..003fc80760 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/CoordinateOperationFinder.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/CoordinateOperationFinder.java
@@ -224,6 +224,15 @@ final class CoordinateOperationFinder implements
Supplier<double[]> {
*/
private boolean isWraparoundDisabled;
+ /**
+ * Whether the {@link #get()} method should accept dimensions that are not
slices in a multi-dimensional cube.
+ * If 0 (the default), the dimensions are required to be slices. If
non-zero, the requirement is relaxed, with
+ * -1 meaning to use the low grid coordinate and +1 meaning to use the
high grid coordinate.
+ *
+ * @see #relaxSliceRequirement(byte)
+ */
+ private byte relaxSliceRequirement;
+
/**
* Creates a new finder initialized to {@link PixelInCell#CELL_CORNER}
anchor.
*
@@ -268,7 +277,7 @@ final class CoordinateOperationFinder implements
Supplier<double[]> {
anchor = newValue;
gridToCRS = null;
crsToGrid = null;
- if (coordinates != null) {
+ if (hasUsedConstantValues()) {
coordinates = null;
changeOfCRS = null;
forwardChangeOfCRS = null;
@@ -278,6 +287,18 @@ final class CoordinateOperationFinder implements
Supplier<double[]> {
}
}
+ /**
+ * Sets whether the {@link #get()} method should accept dimensions that
are not slices in a multi-dimensional cube.
+ *
+ * @param mode 0 to require slices, -1 for using low grid coordinates,
or +1 for high grid coordinates.
+ */
+ final void relaxSliceRequirement(final byte mode) {
+ relaxSliceRequirement = mode;
+ if (hasUsedConstantValues()) {
+ setAnchor(anchor); // For cleaning the cache.
+ }
+ }
+
/**
* Disables completely all wraparounds operation.
*
@@ -720,7 +741,7 @@ apply: if (forwardChangeOfCRS == null) {
* be given to the missing dimensions, then those values are returned.
* Otherwise this method returns {@code null}.
*
- * <p>The returned array has a length equals to the number of dimensions
in the target CRS.
+ * <p>The returned array has a length equals to the number of dimensions
in the target <abbr>CRS</abbr>.
* Only coordinates in dimensions without source (<var>t</var> in the
above example) will be used.
* All other coordinate values will be ignored.</p>
*
@@ -736,10 +757,17 @@ apply: if (forwardChangeOfCRS == null) {
Arrays.fill(gc, Double.NaN);
final GridExtent extent = target.getExtent();
for (int i=0; i<gc.length; i++) {
- final long low = extent.getLow(i);
- if (low == extent.getHigh(i)) {
+ long low = extent.getLow (i);
+ long high = extent.getHigh(i);
+ if (low == high || relaxSliceRequirement < 0) {
gc[i] = low;
+ } else if (relaxSliceRequirement > 0) {
+ if (anchor != PixelInCell.CELL_CENTER) {
+ high++; // From inclusive to exclusive.
+ }
+ gc[i] = high;
}
+ // Otherwise keep the NaN value.
}
/*
* At this point, the only grid coordinates with finite values are
the ones where the
@@ -757,6 +785,13 @@ apply: if (forwardChangeOfCRS == null) {
return coordinates;
}
+ /**
+ * Returns {@code true} if {@link #get()} has been invoked and computed
coordinates.
+ */
+ final boolean hasUsedConstantValues() {
+ return coordinates != null;
+ }
+
/**
* Configures the accuracy hints on the given processor.
*
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
index 3bb5d54224..c3087896bc 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
@@ -569,14 +569,15 @@ public class GridDerivation {
final MathTransform nowraparound;
final var finder = new CoordinateOperationFinder(areaOfInterest,
base);
finder.verifyPresenceOfCRS(false);
+ finder.relaxSliceRequirement((byte) -1);
final GridExtent domain = areaOfInterest.extent;
if (domain == null) {
finder.setAnchor(PixelInCell.CELL_CENTER);
finder.nowraparound();
- nowraparound = finder.gridToGrid();
+ nowraparound = finder.gridToGrid(); // We will use only
the scale factors.
} else {
/*
- * Get the transform from the base grid to the grid of
`areaOfInterest`.
+ * Get the transform from the grid of `areaOfInterest` to the
base grid.
* There is two variants, depending on whether the user wants
tight box:
*
* - Default: map pixel corners with exclusive upper grid
coordinate value.
@@ -587,14 +588,50 @@ public class GridDerivation {
finder.setAnchor(PixelInCell.CELL_CENTER);
} // Else default value is PixelInCell.CELL_CORNER.
final MathTransform gridToGrid = finder.gridToGrid();
+ final MathTransform gridToGridHigh;
+ if (finder.hasUsedConstantValues()) {
+ finder.relaxSliceRequirement((byte) +1);
+ gridToGridHigh = finder.gridToGrid();
+ } else {
+ gridToGridHigh = null;
+ }
+ /*
+ * Compute again the transform from `areaOfInterest` grid to
base grid,
+ * but this time with no special treatment for longitude
wraparound.
+ * The main intent is to get the scale factors, which are
hidden when
+ * a wraparound shift is bundled in the transform.
+ */
finder.setAnchor(tight ? PixelInCell.CELL_CORNER :
PixelInCell.CELL_CENTER);
finder.nowraparound();
- nowraparound = finder.gridToGrid(); // We will use only the
scale factors.
+ final MathTransform nowraparoundHigh;
+ if (gridToGridHigh != null) {
+ nowraparoundHigh = finder.gridToGrid();
+ finder.relaxSliceRequirement((byte) -1);
+ } else {
+ nowraparoundHigh = null;
+ }
+ nowraparound = finder.gridToGrid();
+ /*
+ * Converts the grid extent of the area of interest to the
grid coordinates of the base.
+ * We may get one or two envelopes, depending on whether there
is a longitude wraparound.
+ * If the area of interest has less dimensions than the base
grid, we may need to compute
+ * more envelopes for enclosing the full span of dimensions
that are not in `areaOfInterest`.
+ */
final GeneralEnvelope[] envelopes;
- if (gridToGrid.isIdentity()) {
+ if (gridToGrid.isIdentity() && (gridToGridHigh == null ||
gridToGridHigh.isIdentity())) {
envelopes = new GeneralEnvelope[]
{domain.toEnvelope(tight)};
} else {
envelopes = domain.toEnvelopes(gridToGrid, tight,
nowraparound, null);
+ if (gridToGridHigh != null) {
+ final GeneralEnvelope[] high =
domain.toEnvelopes(gridToGridHigh, tight, nowraparoundHigh, null);
+ for (int i = Math.min(envelopes.length, high.length);
--i >= 0;) {
+ /*
+ * TODO: actually, we have no guarantee that the
envelopes at the same index match.
+ * We need to find a more reliable algorithm,
maybe by checking intersection first.
+ */
+ envelopes[i].add(high[i]);
+ }
+ }
}
setBaseExtentClipped(tight, envelopes);
if (baseExtent != base.extent && baseExtent.equals(domain)) {
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/SliceGeometry.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/SliceGeometry.java
index d27bbd82c8..ec6e73472a 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/SliceGeometry.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/SliceGeometry.java
@@ -316,7 +316,7 @@ final class SliceGeometry implements
Function<RenderedImage, GridGeometry> {
}
numRow += derivative.getNumRow();
if (dimCRS < 0) {
- dimCRS = gridDimensions.length;
+ dimCRS = Math.min(gridDimensions.length,
gridToCRS.getTargetDimensions());
}
/*
* Search for the greatest scale coefficient. For the greatest value,
take the row as the target
diff --git
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridDerivationTest.java
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridDerivationTest.java
index 86fe67d11e..0ed8c3b205 100644
---
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridDerivationTest.java
+++
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridDerivationTest.java
@@ -385,6 +385,55 @@ public final class GridDerivationTest extends TestCase {
assertMatrixEquals(expected, gridToCRS, STRICT, "gridToCRS");
}
+ /**
+ * Tests {@link GridDerivation#subgrid(GridGeometry)} using a grid with
less dimensions
+ * than the source grid geometry when the extra dimensions are not a slice.
+ *
+ * <h4>Note on cache dependency</h4>
+ * Another difference between this test and {@link
#testSubgridWithLessDimensions()} is that
+ * this test uses a geographic area covering the world. It has subtile
implications in the way
+ * that {@link
org.apache.sis.referencing.operation.CoordinateOperationFinder} uses its cache.
+ * See in particular the {@code canStoreInCache} flag of the latter class.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/SIS-610">SIS-610</a>
+ */
+ @Test
+ public void testSubgridWithLessDimensionsNoSlice() {
+ final var envelope = new GeneralEnvelope(HardCodedCRS.WGS84_4D);
+ envelope.setRange(0, -180, 180);
+ envelope.setRange(1, -90, 90);
+ envelope.setRange(2, 100, 300);
+ envelope.setRange(3, 3, 6);
+ final var extent = new GridExtent(null, null, new long[] {2, 2, 3, 3},
false);
+ final var grid = new GridGeometry(extent, envelope,
GridOrientation.DISPLAY);
+ final var env2D = new GeneralEnvelope(HardCodedCRS.WGS84);
+ env2D.setRange(0, -51, 153);
+ env2D.setRange(1, 68, 89);
+ final var aoi = new GridGeometry(new GridExtent(100, 100), env2D,
GridOrientation.HOMOTHETY);
+ /*
+ * Test with rounding to nearest grid coordinates. The AOI has a range
of latitude values which
+ * is fully enclosed in the voxel at index y=1, while the range of
longitude values intersects
+ * voxels at indexes x=[0…1]. However, because the rounding mode is
nearest and the lower bound
+ * is closer to x=1, the result is x=[1].
+ */
+ GridGeometry slice = grid.derive().subgrid(aoi).build();
+ assertEquals(grid.getGridToCRS(PixelInCell.CELL_CENTER),
+ slice.getGridToCRS(PixelInCell.CELL_CENTER));
+ assertExtentEquals(new long[] {1, 0, 0, 0},
+ new long[] {1, 0, 2, 2},
+ slice.getExtent());
+ /*
+ * Same as above but with rounding mode to "enclosed".
+ * The range in dimension of longitude become x=[0…1].
+ */
+ slice =
grid.derive().rounding(GridRoundingMode.ENCLOSING).subgrid(aoi).build();
+ assertEquals(grid.getGridToCRS(PixelInCell.CELL_CENTER),
+ slice.getGridToCRS(PixelInCell.CELL_CENTER));
+ assertExtentEquals(new long[] {0, 0, 0, 0},
+ new long[] {1, 0, 2, 2},
+ slice.getExtent());
+ }
+
/**
* Tests {@link GridDerivation#subgrid(Envelope, double...)} on a grid
using a polar projection.
* The test also uses a geographic envelope with more dimensions than the
source grid geometry.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationContext.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationContext.java
index 22936847f6..3f91b17c70 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationContext.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationContext.java
@@ -23,6 +23,7 @@ import org.opengis.metadata.extent.Extent;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.OperationNotFoundException;
import org.apache.sis.referencing.privy.CoordinateOperations;
import org.apache.sis.metadata.iso.extent.DefaultExtent;
import org.apache.sis.metadata.iso.extent.Extents;
@@ -225,16 +226,17 @@ public class CoordinateOperationContext implements
Serializable {
}
/**
- * Invoked when some coordinates in the target CRS cannot be computed from
coordinates in the source CRS.
- * For example if the source CRS has (<var>x</var>, <var>y</var>) axes and
the target CRS has (<var>x</var>,
- * <var>y</var>, <var>t</var>) axes, then this method is invoked for
determining which value to assign to the
- * <var>t</var> coordinate. In some cases the user can tell that the
coordinate should be set to a constant value.
+ * Invoked when at least one coordinate in the target <abbr>CRS</abbr>
cannot be computed from the coordinates in
+ * the source <abbr>CRS</abbr>. For example, if the source
<abbr>CRS</abbr> has (<var>x</var>, <var>y</var>) axes
+ * and the target <abbr>CRS</abbr> has (<var>x</var>, <var>y</var>,
<var>t</var>) axes,
+ * then this method is invoked for determining which value to assign to
the <var>t</var> coordinate.
+ * In some cases, the user can tell that the coordinate should be set to a
constant value.
*
- * <p>If this method returns {@code null} (which is the default), then the
{@link CoordinateOperationFinder} caller
- * will throw an {@link
org.opengis.referencing.operation.OperationNotFoundException}. Otherwise the
returned array
- * should have a length equals to the number of dimensions in the full
(usually compound) target CRS.
- * Only coordinate values in dimensions without source (the <var>t</var>
dimension in the above example) will be used.
- * All other coordinate values will be ignored.
+ * <p>If this method returns {@code null}, then the {@link
CoordinateOperationFinder} caller will throw an
+ * {@link OperationNotFoundException}. Otherwise, the returned array
should have a length equals to the number
+ * of dimensions in the full (usually compound) target <abbr>CRS</abbr>.
Only coordinate values in dimensions
+ * without source (the <var>t</var> dimension in the above example) will
be used.
+ * All other coordinate values will be ignored.</p>
*
* @return coordinate values to take as constants for the specified target
component, or {@code null} if none.
* @throws TransformException if the coordinates cannot be computed. This
exception may occur when the constant
@@ -251,4 +253,12 @@ public class CoordinateOperationContext implements
Serializable {
}
return null;
}
+
+ /**
+ * Returns whether it is safe to use cached operation.
+ * This is {@code false} if the operation result may depend on external
configuration.
+ */
+ static boolean canReadFromCache() {
+ return CoordinateOperations.CONSTANT_COORDINATES.get() == null;
+ }
}
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 d28975397b..e127c1d49f 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
@@ -139,7 +139,15 @@ public class CoordinateOperationFinder extends
CoordinateOperationRegistry {
/**
* Whether this finder instance is allowed to use {@link
DefaultCoordinateOperationFactory#cache}.
*/
- private final boolean useCache;
+ private final boolean canReadFromCache;
+
+ /**
+ * Whether the operation can be cached. This flag shall be {@code false} if
+ * the operation depends on parameters that may vary between two
executions.
+ *
+ * @see #canStoreInCache()
+ */
+ private boolean canStoreInCache;
/**
* Creates a new instance for the given factory and context.
@@ -158,7 +166,8 @@ public class CoordinateOperationFinder extends
CoordinateOperationRegistry {
super(registry, factory, context);
identifierOfStepCRS = new HashMap<>(8);
previousSearches = new HashMap<>(8);
- useCache = (context == null) && (factory == factorySIS);
+ canReadFromCache = (context == null) && (factory == factorySIS) &&
CoordinateOperationContext.canReadFromCache();
+ canStoreInCache = (context == null);
}
/**
@@ -243,7 +252,7 @@ public class CoordinateOperationFinder extends
CoordinateOperationRegistry {
* is not in the cache, store the key in our internal map for
preventing infinite recursion.
*/
final CRSPair key = new CRSPair(sourceCRS, targetCRS);
- if (useCache && stopAtFirst && !previousSearches.isEmpty()) {
+ if (canReadFromCache && stopAtFirst && !previousSearches.isEmpty()) {
final CoordinateOperation op = factorySIS.cache.peek(key);
if (op != null) return asList(op); // Must be a modifiable
list as per this method contract.
}
@@ -858,6 +867,7 @@ public class CoordinateOperationFinder extends
CoordinateOperationRegistry {
final SubOperationInfo info = infos[i];
final CoordinateReferenceSystem source = stepComponents[i];
final CoordinateReferenceSystem target =
targetComponents.get(info.targetComponentIndex);
+ canStoreInCache &= info.canStoreInCache;
/*
* In order to compute `stepTargetCRS`, replace in-place a single
element in `stepComponents`.
* For each step except the last one, `stepTargetCRS` is a mix of
target CRS and source CRS.
@@ -910,6 +920,9 @@ public class CoordinateOperationFinder extends
CoordinateOperationRegistry {
stepSourceCRS.getCoordinateSystem().getDimension(),
targetCRS.getCoordinateSystem().getDimension());
operation = concatenate(operation,
createFromAffineTransform(CONSTANTS, stepSourceCRS, targetCRS, null, m));
+ for (int i = stepComponents.length; i < infos.length; i++) {
+ canStoreInCache &= infos[i].canStoreInCache;
+ }
} catch (TransformException e) {
throw new FactoryException(notFoundMessage(sourceCRS, targetCRS),
e);
}
@@ -1172,4 +1185,12 @@ public class CoordinateOperationFinder extends
CoordinateOperationRegistry {
private String canNotInvert(final DerivedCRS crs) {
return resources().getString(Resources.Keys.NonInvertibleOperation_1,
label(crs.getConversionFromBase()));
}
+
+ /**
+ * Returns whether the operation can be cached. This is {@code false} if
+ * the operation depends on parameters that may vary between two
executions.
+ */
+ final boolean canStoreInCache() {
+ return canStoreInCache;
+ }
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
index 7c3a3e067b..8e24b9dc6e 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
@@ -704,20 +704,16 @@ next: for (SingleCRS component :
CRS.getSingleComponents(targetCRS)) {
handler = null;
op = null;
}
+ boolean canStoreInCache = true;
try {
if (handler == null || (op = handler.peek()) == null) {
- CoordinateOperationAuthorityFactory registry = null;
- if (USE_EPSG_FACTORY) {
- final AuthorityFactory candidate =
CRS.getAuthorityFactory(Constants.EPSG);
- if (candidate instanceof
CoordinateOperationAuthorityFactory) {
- registry = (CoordinateOperationAuthorityFactory)
candidate;
- }
- }
- op = createOperationFinder(registry,
context).createOperation(sourceCRS, targetCRS);
+ final CoordinateOperationFinder finder =
createOperationFinder(getFactorySIS(), context);
+ op = finder.createOperation(sourceCRS, targetCRS);
+ canStoreInCache = finder.canStoreInCache();
}
} finally {
if (handler != null) {
- handler.putAndUnlock(op);
+ handler.putAndUnlock(canStoreInCache ? op : null);
}
}
return op;
@@ -756,9 +752,20 @@ next: for (SingleCRS component :
CRS.getSingleComponents(targetCRS)) {
final
CoordinateOperationContext context)
throws OperationNotFoundException, FactoryException
{
- final AuthorityFactory registry = USE_EPSG_FACTORY ?
CRS.getAuthorityFactory(Constants.EPSG) : null;
- return createOperationFinder((registry instanceof
CoordinateOperationAuthorityFactory) ?
- (CoordinateOperationAuthorityFactory) registry : null,
context).createOperations(sourceCRS, targetCRS);
+ return createOperationFinder(getFactorySIS(),
context).createOperations(sourceCRS, targetCRS);
+ }
+
+ /**
+ * Returns the Apache <abbr>SIS</abbr> implementation of the
<abbr>EPSG</abbr> factory, or {@code null} if none.
+ */
+ private static CoordinateOperationAuthorityFactory getFactorySIS() throws
FactoryException {
+ if (USE_EPSG_FACTORY) {
+ AuthorityFactory registry =
CRS.getAuthorityFactory(Constants.EPSG);
+ if (registry instanceof CoordinateOperationAuthorityFactory) {
+ return (CoordinateOperationAuthorityFactory) registry;
+ }
+ }
+ return null;
}
/**
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 6b63c2b0d1..767ba53262 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
@@ -116,6 +116,12 @@ final class SubOperationInfo {
*/
final int targetComponentIndex;
+ /**
+ * Whether this operation can be cached. This flag shall be {@code false}
if
+ * the operation depends on parameters that may vary between two
executions.
+ */
+ final boolean canStoreInCache;
+
/**
* Creates a new instance wrapping the given coordinate operation or
coordinate constants.
* Exactly one of {@code operation} or {@code constants} shall be non-null.
@@ -123,7 +129,7 @@ final class SubOperationInfo {
private SubOperationInfo(final CoordinateOperation operation, final
double[] constants,
final int sourceLowerDimension, final int
sourceUpperDimension,
final int targetLowerDimension, final int
targetUpperDimension,
- final int targetComponentIndex)
+ final int targetComponentIndex, final boolean
canStoreInCache)
{
this.operation = operation;
this.constants = constants;
@@ -132,6 +138,7 @@ final class SubOperationInfo {
this.targetLowerDimension = targetLowerDimension;
this.targetUpperDimension = targetUpperDimension;
this.targetComponentIndex = targetComponentIndex;
+ this.canStoreInCache = canStoreInCache;
assert (operation == null) != (constants == null);
}
@@ -216,7 +223,7 @@ next: for (int targetComponentIndex = 0;
targetComponentIndex < infos.length;
operation, null,
sourceLowerDimension,
sourceUpperDimension,
targetLowerDimension,
targetUpperDimension,
- targetComponentIndex);
+ targetComponentIndex, true);
if (failure != null) {
CoordinateOperationRegistry.recoverableException("decompose", failure);
@@ -253,7 +260,7 @@ next: for (int targetComponentIndex = 0;
targetComponentIndex < infos.length;
null, constants,
sourceUpperDimension, sourceUpperDimension,
targetLowerDimension, targetUpperDimension,
- targetComponentIndex);
+ targetComponentIndex, false);
}
return infos;
}