This is an automated email from the ASF dual-hosted git repository.
jsorel pushed a commit to branch feat/sourceDomainExpansion
in repository https://gitbox.apache.org/repos/asf/sis.git
commit fbd5f3134ae9647dba14e9b9cea6de91cfdfcc7a
Author: jsorel <johann.sorel@geomatys.com>
AuthorDate: Tue Sep 1 14:02:57 2020 +0200
Add coverage query expansion test cases, add readonly memory grid resource
---
.../sis/internal/storage/MemoryGridResource.java | 143 +++++++++++++++++++++
.../internal/storage/query/CoverageQueryTest.java | 120 +++++++++++++++++
.../apache/sis/test/suite/StorageTestSuite.java | 1 +
3 files changed, 264 insertions(+)
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryGridResource.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryGridResource.java
new file mode 100644
index 0000000..b451ca5
--- /dev/null
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryGridResource.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.storage;
+
+import java.awt.image.RenderedImage;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.sis.coverage.SampleDimension;
+import org.apache.sis.coverage.grid.GridCoverage;
+import org.apache.sis.coverage.grid.GridCoverage2D;
+import org.apache.sis.coverage.grid.GridCoverageBuilder;
+import org.apache.sis.coverage.grid.GridDerivation;
+import org.apache.sis.coverage.grid.GridExtent;
+import org.apache.sis.coverage.grid.GridGeometry;
+import org.apache.sis.coverage.grid.GridRoundingMode;
+import org.apache.sis.image.ImageProcessor;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.event.StoreListeners;
+import org.apache.sis.util.ArgumentChecks;
+import org.opengis.referencing.datum.PixelInCell;
+
+/**
+ * A GridCoverage resource in memory. The GridCoverage is specified at construction time.
+ * Metadata can be specified by overriding {@link #createMetadata(MetadataBuilder)}.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 1.1
+ * @since 1.1
+ * @module
+ */
+public class MemoryGridResource extends AbstractGridResource {
+
+ private final GridCoverage2D coverage;
+
+ /**
+ * Creates a new coverage stored in memory.
+ *
+ * @param parent listeners of the parent resource, or {@code null} if none.
+ * @param coverage stored coverage, coverage will not be copied, can not be null.
+ */
+ public MemoryGridResource(final StoreListeners parent, final GridCoverage2D coverage)
{
+ super(parent);
+ ArgumentChecks.ensureNonNull("coverage", coverage);
+ this.coverage = coverage;
+ }
+
+ /**
+ * {@inheritDoc }
+ *
+ * @return extent of grid coordinates together with their mapping to "real world" coordinates.
+ * @throws DataStoreException if an error occurred while reading definitions from the
underlying data store.
+ */
+ @Override
+ public GridGeometry getGridGeometry() throws DataStoreException {
+ return coverage.getGridGeometry();
+ }
+
+ /**
+ * {@inheritDoc }
+ *
+ * @return ranges of sample values together with their mapping to "real values".
+ * @throws DataStoreException if an error occurred while reading definitions from the
underlying data store.
+ */
+ @Override
+ public List<SampleDimension> getSampleDimensions() throws DataStoreException {
+ return coverage.getSampleDimensions();
+ }
+
+ /**
+ * {@inheritDoc }
+ *
+ * @param domain desired grid extent and resolution, or {@code null} for reading the
whole domain.
+ * @param range 0-based indices of sample dimensions to read, or {@code null} or an
empty sequence for reading them all.
+ * @return the grid coverage for the specified domain and range.
+ * @throws DataStoreException if an error occurred while reading the grid coverage data.
+ */
+ @Override
+ public GridCoverage read(GridGeometry domain, int... range) throws DataStoreException
{
+
+ //quick return of the original coverage
+ if (domain == null && (range == null || range.length == 0)) {
+ return coverage;
+ }
+
+ /*
+ Subsampling is ignored because it is an expensive operation.
+ Clipping and range selection are light and current implementation
+ do not copy any data.
+ */
+ GridGeometry areaOfInterest = coverage.getGridGeometry();
+ GridExtent intersection = areaOfInterest.getExtent();
+ if (domain != null) {
+ final GridDerivation derivation = getGridGeometry().derive()
+ .rounding(GridRoundingMode.ENCLOSING)
+ .subgrid(domain);
+ intersection = derivation.getIntersection();
+ /*
+ Extent is left as null, the grid coverage builder will extract the size from
the image.
+ Image size and offset may not be exactly what was requested by the intersection.
+ */
+ areaOfInterest = new GridGeometry(null,
+ PixelInCell.CELL_CENTER,
+ areaOfInterest.getGridToCRS(PixelInCell.CELL_CENTER),
+ areaOfInterest.getCoordinateReferenceSystem());
+ }
+
+ RenderedImage render = coverage.render(intersection);
+
+ /*
+ Select range.
+ */
+ List<SampleDimension> sampleDimensions = coverage.getSampleDimensions();
+ if (range != null && range.length > 0) {
+ render = new ImageProcessor().selectBands(render, range);
+ final List<SampleDimension> sds = new ArrayList<>();
+ for (int i : range) {
+ sds.add(sampleDimensions.get(i));
+ }
+ sampleDimensions = sds;
+ }
+
+ final GridCoverageBuilder gcb = new GridCoverageBuilder();
+ gcb.setValues(render);
+ gcb.setRanges(sampleDimensions);
+ gcb.setDomain(areaOfInterest);
+ return gcb.build();
+ }
+
+}
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/CoverageQueryTest.java
b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/CoverageQueryTest.java
new file mode 100644
index 0000000..2c8e3fd
--- /dev/null
+++ b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/CoverageQueryTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.storage.query;
+
+import java.awt.image.BufferedImage;
+import org.apache.sis.coverage.grid.GridCoverage;
+import org.apache.sis.coverage.grid.GridCoverage2D;
+import org.apache.sis.coverage.grid.GridCoverageBuilder;
+import org.apache.sis.coverage.grid.GridExtent;
+import org.apache.sis.coverage.grid.GridGeometry;
+import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
+import org.apache.sis.internal.storage.MemoryGridResource;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.GridCoverageResource;
+import org.apache.sis.test.TestCase;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opengis.metadata.spatial.DimensionNameType;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.datum.PixelInCell;
+
+/**
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 1.1
+ * @since 1.1
+ */
+public final strictfp class CoverageQueryTest extends TestCase {
+
+ /**
+ * Verify source domain expansion parameter is used.
+ */
+ @Test
+ public void sourceExpansionTest() throws DataStoreException {
+
+ final CoordinateReferenceSystem crs = CommonCRS.WGS84.normalizedGeographic();
+ final AffineTransform2D gridToCrs = new AffineTransform2D(1, 0, 0, 1, 0, 0);
+ final GridCoverageResource resource;
+ { //create resource
+ final GridGeometry grid = new GridGeometry(new GridExtent(100, 100), PixelInCell.CELL_CENTER,
gridToCrs, crs);
+ final BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
+
+ final GridCoverageBuilder gcb = new GridCoverageBuilder();
+ gcb.setDomain(grid);
+ gcb.setValues(image);
+ final GridCoverage coverage = gcb.build();
+ resource = new MemoryGridResource(null, (GridCoverage2D) coverage);
+ }
+
+ { // test without any parameter
+ final CoverageQuery query = new CoverageQuery();
+ final GridCoverageResource subres = resource.subset(query);
+ Assert.assertEquals(resource.getGridGeometry(), subres.getGridGeometry());
+ }
+
+ { // test with sub grid geometry
+ final GridGeometry subGrid = new GridGeometry(new GridExtent(
+ new DimensionNameType[]{DimensionNameType.COLUMN, DimensionNameType.ROW},
+ new long[]{20, 20}, new long[]{40, 40}, true),
+ PixelInCell.CELL_CENTER, gridToCrs, crs);
+
+ final CoverageQuery query = new CoverageQuery();
+ query.setDomain(subGrid);
+
+ final GridCoverageResource subres = resource.subset(query);
+ Assert.assertEquals(subGrid, subres.getGridGeometry());
+ }
+
+ { // test with sub grid geometry + expansion
+ final GridGeometry subGrid = new GridGeometry(new GridExtent(
+ new DimensionNameType[]{DimensionNameType.COLUMN, DimensionNameType.ROW},
+ new long[]{20, 20}, new long[]{40, 40}, true),
+ PixelInCell.CELL_CENTER, gridToCrs, crs);
+
+ final CoverageQuery query = new CoverageQuery();
+ query.setDomain(subGrid);
+ query.setSourceDomainExpansion(3);
+
+ final GridCoverageResource subres = resource.subset(query);
+
+ final GridGeometry expGrid = new GridGeometry(new GridExtent(
+ new DimensionNameType[]{DimensionNameType.COLUMN, DimensionNameType.ROW},
+ new long[]{17, 17}, new long[]{43, 43}, true),
+ PixelInCell.CELL_CENTER, gridToCrs, crs);
+
+ Assert.assertEquals(expGrid, subres.getGridGeometry());
+
+
+ //read operation must add the expected margins
+ //this last test is only to avoid regression
+ //GridCoverage2D implementation returns a larger area then requested
+ final GridGeometry readGrid = new GridGeometry(new GridExtent(
+ new DimensionNameType[]{DimensionNameType.COLUMN, DimensionNameType.ROW},
+ new long[]{30, 30}, new long[]{35, 35}, true),
+ PixelInCell.CELL_CENTER, gridToCrs, crs);
+ GridCoverage coverage = subres.read(readGrid);
+
+ final GridGeometry expReadGrid = resource.getGridGeometry();
+
+ Assert.assertEquals(expReadGrid, coverage.getGridGeometry());
+
+ }
+ }
+
+}
diff --git a/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
b/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
index bbabdf6..600a9ad 100644
--- a/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
+++ b/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
@@ -44,6 +44,7 @@ import org.junit.BeforeClass;
org.apache.sis.storage.ProbeResultTest.class,
org.apache.sis.storage.StorageConnectorTest.class,
org.apache.sis.storage.event.StoreListenersTest.class,
+ org.apache.sis.internal.storage.query.CoverageQueryTest.class,
org.apache.sis.internal.storage.query.SimpleQueryTest.class,
org.apache.sis.internal.storage.xml.MimeTypeDetectorTest.class,
org.apache.sis.internal.storage.xml.StoreProviderTest.class,
|