/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2012, 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.display2d.service; import java.awt.Dimension; import java.awt.geom.AffineTransform; import java.awt.image.RenderedImage; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.concurrent.CancellationException; import org.geotoolkit.coverage.GridSampleDimension; import org.geotoolkit.coverage.grid.GeneralGridGeometry; import org.geotoolkit.coverage.grid.GridCoverageBuilder; import org.geotoolkit.coverage.io.CoverageStoreException; import org.geotoolkit.coverage.io.GridCoverageReadParam; import org.geotoolkit.coverage.io.GridCoverageReader; import org.geotoolkit.display.PortrayalException; import org.geotoolkit.factory.FactoryFinder; import org.geotoolkit.referencing.ReferencingUtilities; 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.TransformException; import org.opengis.util.GenericName; import org.opengis.util.NameFactory; import org.opengis.util.NameSpace; import org.apache.sis.geometry.Envelopes; import org.apache.sis.util.Utilities; /** * Manipulate a SceneDef as a CoverageReader. * This allow to manipulate an aggregation of several different layers as if * it was a single coverage layer. * * @author Johann Sorel (Geomatys) * @module */ public class PortrayalCoverageReader extends GridCoverageReader { private final SceneDef scene; private final GenericName name; private String contextName; public PortrayalCoverageReader(final SceneDef scene) { this.scene = scene; contextName = scene.getContext().getName(); if(contextName == null){ contextName = "portrayal"; } final NameFactory dnf = FactoryFinder.getNameFactory(null); final NameSpace ns = dnf.createNameSpace(dnf.createGenericName(null, contextName), null); name = dnf.createLocalName(ns, contextName); } @Override public List<? extends GenericName> getCoverageNames() throws CoverageStoreException, CancellationException { return Collections.singletonList(name); } @Override public GeneralGridGeometry getGridGeometry(int index) throws CoverageStoreException, CancellationException { //we only know the envelope final GeneralGridGeometry gridGeom; try { gridGeom = new GeneralGridGeometry(null, null, scene.getContext().getBounds()); } catch (IOException ex) { throw new CoverageStoreException(ex.getMessage(),ex); } return gridGeom; } @Override public List<GridSampleDimension> getSampleDimensions(int index) throws CoverageStoreException, CancellationException { return null; } @Override public GridCoverage read(int index, GridCoverageReadParam param) throws CoverageStoreException, CancellationException { if(index != 0){ throw new CoverageStoreException("Invalid Image index."); } if(param == null){ param = new GridCoverageReadParam(); } final int[] desBands = param.getDestinationBands(); final int[] sourceBands = param.getSourceBands(); if(desBands != null || sourceBands != null){ throw new CoverageStoreException("Source or destination bands can not be used on portrayal images."); } CoordinateReferenceSystem crs = param.getCoordinateReferenceSystem(); Envelope paramEnv = param.getEnvelope(); double[] resolution = param.getResolution(); //verify envelope and crs if(crs == null && paramEnv == null){ //use the max extent paramEnv = getGridGeometry(0).getEnvelope(); crs = paramEnv.getCoordinateReferenceSystem(); }else if(crs != null && paramEnv != null){ //check the envelope crs matches given crs if(!Utilities.equalsIgnoreMetadata(paramEnv.getCoordinateReferenceSystem(),crs)){ throw new CoverageStoreException("Invalid parameters : envelope crs do not match given crs."); } }else if(paramEnv != null){ //use the envelope crs crs = paramEnv.getCoordinateReferenceSystem(); }else if(crs != null){ //use the given crs paramEnv = getGridGeometry(0).getEnvelope(); try { paramEnv = Envelopes.transform(paramEnv, crs); } catch (TransformException ex) { throw new CoverageStoreException("Could not transform coverage envelope to given crs."); } } //estimate resolution if not given if(resolution == null){ //we arbitrarly choose 1000 pixel on first axis, layers can have an infinite resolution. resolution = new double[2]; resolution[0] = paramEnv.getSpan(0)/1000; resolution[1] = resolution[0] * (paramEnv.getSpan(1)/paramEnv.getSpan(0)); } //calculate final image dimension final Dimension dim = new Dimension( (int)(paramEnv.getSpan(0) / resolution[0]), (int)(paramEnv.getSpan(1) / resolution[1])); //calculate final grid to crs transform final AffineTransform gridToCRS = ReferencingUtilities.toAffine(dim, paramEnv); final CanvasDef canvas = new CanvasDef(dim, null); final ViewDef view = new ViewDef(paramEnv); final RenderedImage image; try { image = DefaultPortrayalService.portray(canvas, scene, view); } catch (PortrayalException ex) { throw new CoverageStoreException(ex.getMessage(),ex); } //build the coverage --------------------------------------------------- final GridCoverageBuilder gcb = new GridCoverageBuilder(); gcb.setName(contextName); gcb.setRenderedImage(image); gcb.setPixelAnchor(PixelInCell.CELL_CORNER); gcb.setGridToCRS(gridToCRS); gcb.setCoordinateReferenceSystem(crs); return gcb.build(); } }