/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2015, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.coverage.amended; import java.util.List; import java.util.concurrent.CancellationException; import org.apache.sis.geometry.GeneralEnvelope; import org.apache.sis.referencing.operation.transform.MathTransforms; import org.geotoolkit.coverage.GridSampleDimension; import org.geotoolkit.coverage.grid.GeneralGridGeometry; import org.geotoolkit.coverage.grid.GridCoverageBuilder; import org.geotoolkit.coverage.io.CoverageReader; import org.geotoolkit.coverage.io.CoverageStoreException; import org.geotoolkit.coverage.io.GridCoverageReadParam; import org.geotoolkit.coverage.io.GridCoverageReader; import org.geotoolkit.referencing.ReferencingUtilities; import org.opengis.coverage.SampleDimension; import org.opengis.coverage.grid.GridCoverage; import org.opengis.geometry.Envelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.datum.PixelInCell; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; import org.opengis.util.GenericName; import org.apache.sis.geometry.Envelopes; /** * Decorate a coverage reader changing behavior to match overriden properties * in the coverage reference. * * @author Johann Sorel (Geomatys) */ public class AmendedCoverageReader extends GridCoverageReader{ private final AmendedCoverageReference ref; private final GridCoverageReader reader; public AmendedCoverageReader(AmendedCoverageReference ref) throws CoverageStoreException { this.ref = ref; this.reader = ref.getDecorated().acquireReader(); } public CoverageReader getDecorated(){ return reader; } /** * Delegates to wrapped coverage reader. * * @return wrapped real coverage names * @throws CoverageStoreException * @throws CancellationException */ @Override public List<? extends GenericName> getCoverageNames() throws CoverageStoreException, CancellationException { return reader.getCoverageNames(); } /** * Returns the corrected grid geometry based on overriden properties in the coverage reference. * * @param index : image index * @return GeneralGridGeometry, never null * @throws CoverageStoreException * @throws CancellationException */ @Override public GeneralGridGeometry getGridGeometry(int index) throws CoverageStoreException, CancellationException { return ref.getGridGeometry(index); } /** * Returns the corrected sample dimensions based on overriden properties in the coverage reference. * * @param index : image index * @return sample dimensions, can be null or empty * @throws CoverageStoreException * @throws CancellationException */ @Override public List<GridSampleDimension> getSampleDimensions(int index) throws CoverageStoreException, CancellationException { return ref.getSampleDimensions(index); } /** * Decorates and fixes the reading parameters passed and returned by the wrapped coverage reader * to match overriden properties in the coverage reference. * * * @param index : image index * @param param : read parameters. * @return GridCoverage * @throws CoverageStoreException * @throws CancellationException */ @Override public GridCoverage read(int index, GridCoverageReadParam param) throws CoverageStoreException, CancellationException { GridCoverage coverage; if(ref.isGridGeometryOverriden()){ final CoordinateReferenceSystem overrideCRS = ref.getOverrideCRS(); final MathTransform overrideGridToCrs = ref.getOverrideGridToCrs(); final PixelInCell overridePixelInCell = ref.getOverridePixelInCell(); final GeneralGridGeometry overrideGridGeometry = ref.getGridGeometry(index); final GeneralGridGeometry originalGridGeometry = ref.getOriginalGridGeometry(index); //convert parameters to fit overrides double[] queryRes = param==null ? null : param.getResolution(); CoordinateReferenceSystem queryCrs = param==null ? null : param.getCoordinateReferenceSystem(); Envelope queryEnv = param==null ? null : param.getEnvelope(); //find requested envelope if(queryEnv==null && queryCrs!=null){ try { queryEnv = Envelopes.transform(overrideGridGeometry.getEnvelope(),queryCrs); } catch (TransformException ex) { throw new CoverageStoreException(ex.getMessage(), ex); } } //convert resolution to coverage crs double[] coverageRes = queryRes; if(queryRes!=null){ try { coverageRes = ReferencingUtilities.convertResolution(queryEnv, queryRes, overrideGridGeometry.getCoordinateReferenceSystem()); } catch (TransformException ex) { throw new CoverageStoreException(ex.getMessage(), ex); } } //get envelope in coverage crs Envelope coverageEnv; if(queryEnv==null){ //if no envelope is defined, use the full extent coverageEnv = overrideGridGeometry.getEnvelope(); }else{ try { coverageEnv = Envelopes.transform(queryEnv, overrideGridGeometry.getCoordinateReferenceSystem()); } catch (TransformException ex) { throw new CoverageStoreException(ex.getMessage(), ex); } } //change the crs to original one if(overrideCRS!=null){ coverageEnv = GeneralEnvelope.castOrCopy(coverageEnv); ((GeneralEnvelope)coverageEnv).setCoordinateReferenceSystem( originalGridGeometry.getCoordinateReferenceSystem()); } //change the queried envelope MathTransform fixedToOriginal = null; MathTransform originalToFixed = null; if(overrideGridToCrs!=null || overridePixelInCell!=null){ try { final MathTransform overrideCrsToGrid = overrideGridGeometry.getGridToCRS().inverse(); fixedToOriginal = MathTransforms.concatenate(overrideCrsToGrid, originalGridGeometry.getGridToCRS()); originalToFixed = fixedToOriginal.inverse(); coverageEnv = Envelopes.transform(fixedToOriginal, coverageEnv); coverageEnv = GeneralEnvelope.castOrCopy(coverageEnv); ((GeneralEnvelope)coverageEnv).setCoordinateReferenceSystem( originalGridGeometry.getCoordinateReferenceSystem()); } catch (TransformException ex) { throw new CoverageStoreException(ex); } } //query original reader final GridCoverageReadParam refParam = new GridCoverageReadParam(param); refParam.setResolution(coverageRes); refParam.setCoordinateReferenceSystem(null); refParam.setEnvelope(null); if(coverageEnv!=null){ refParam.setCoordinateReferenceSystem(coverageEnv.getCoordinateReferenceSystem()); refParam.setEnvelope(coverageEnv); } coverage = reader.read(index, refParam); //fix coverage transform and crs final GridCoverageBuilder gcb = new GridCoverageBuilder(); gcb.setGridCoverage(coverage); if(overrideCRS!=null){ gcb.setCoordinateReferenceSystem(overrideCRS); } if(overrideGridToCrs!=null || overridePixelInCell!=null){ final MathTransform localGridToCrs = gcb.getGridToCRS(); final MathTransform localFixedGridToCrs = MathTransforms.concatenate(localGridToCrs, originalToFixed); gcb.setGridToCRS(localFixedGridToCrs); } coverage = gcb.build(); }else{ coverage = reader.read(index, param); } //override sample dimensions final List<GridSampleDimension> overrideDims = ref.getOverrideDims(); if(overrideDims!=null){ final GridCoverageBuilder gcb = new GridCoverageBuilder(); gcb.setGridCoverage(coverage); gcb.setSampleDimensions(overrideDims.toArray(new SampleDimension[overrideDims.size()])); coverage = gcb.build(); } return coverage; } /** * {@inheritDoc } */ @Override public void reset() throws CoverageStoreException { reader.reset(); } /** * {@inheritDoc } */ @Override public void dispose() { ref.getDecorated().recycle(reader); } }