/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2011, Open Source Geospatial Foundation (OSGeo) * * 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.geotools.swing.tool; import java.awt.Rectangle; import java.lang.ref.WeakReference; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.GridEnvelope2D; import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader; import org.geotools.coverage.grid.io.AbstractGridFormat; import org.geotools.geometry.DirectPosition2D; import org.geotools.map.GridReaderLayer; import org.geotools.map.Layer; import org.geotools.parameter.Parameter; import org.geotools.resources.geometry.XRectangle2D; import org.opengis.coverage.PointOutsideCoverageException; import org.opengis.coverage.grid.GridEnvelope; import org.opengis.geometry.DirectPosition; import org.opengis.parameter.GeneralParameterValue; import org.opengis.referencing.datum.PixelInCell; import org.opengis.referencing.operation.MathTransform; /** * Helper class used by {@linkplain InfoTool} to query values in a * {@linkplain org.geotools.map.GridReaderLayer}. * * @author Michael Bedward * @since 8.0 * * @source $URL$ * @version $URL$ */ public class GridReaderLayerHelper extends InfoToolHelper { private static final int CACHED_RASTER_WIDTH = 20; private WeakReference<AbstractGridCoverage2DReader> sourceRef; private GridCoverage2D cachedCoverage; public GridReaderLayerHelper() { } @Override public boolean isSupportedLayer(Layer layer) { return (layer instanceof GridReaderLayer); } @Override public void setLayer(Layer layer) { if (!(layer instanceof GridReaderLayer)) { throw new IllegalArgumentException("layer must be an instance of GridReaderLayer"); } super.setLayer(layer); sourceRef = new WeakReference<AbstractGridCoverage2DReader>( ((GridReaderLayer) layer).getReader()); } @Override public boolean isValid() { return super.isValid() && sourceRef != null && sourceRef.get() != null; } @Override public InfoToolResult getInfo(DirectPosition2D pos) throws Exception { InfoToolResult result = new InfoToolResult(); if (isValid()) { DirectPosition trPos = InfoToolHelperUtils.getTransformed(pos, getContentToLayerTransform()); if (cachedCoverage == null || !cachedCoverage.getEnvelope2D().contains(trPos)) { if (!renewCachedCoverage(trPos)) { return result; } } try { Object objArray = cachedCoverage.evaluate(trPos); Number[] bandValues = InfoToolHelperUtils.asNumberArray(objArray); if (bandValues != null) { result.newFeature("Raw values"); for (int i = 0; i < bandValues.length; i++) { result.setFeatureValue("Band " + i, bandValues[i]); } } } catch (PointOutsideCoverageException e) { // The empty result will be returned } } return result; } private boolean renewCachedCoverage(DirectPosition centrePos) { final Rectangle queryRect = createQueryGridEnvelope(centrePos); if (queryRect.isEmpty()) { return false; } final AbstractGridCoverage2DReader reader = sourceRef.get(); GeneralParameterValue parameter = new Parameter( AbstractGridFormat.READ_GRIDGEOMETRY2D, new GridGeometry2D(new GridEnvelope2D(queryRect), reader.getOriginalGridToWorld(PixelInCell.CELL_CENTER), reader.getCrs())); try { cachedCoverage = (GridCoverage2D) reader.read(new GeneralParameterValue[]{parameter}); return cachedCoverage != null; } catch (Exception ex) { throw new RuntimeException(ex); } } private Rectangle createQueryGridEnvelope(DirectPosition pos) { final AbstractGridCoverage2DReader reader = sourceRef.get(); try { MathTransform worldToGridTransform = reader.getOriginalGridToWorld(PixelInCell.CELL_CORNER).inverse(); DirectPosition midPos = worldToGridTransform.transform(pos, null); int x = (int) midPos.getOrdinate(0); int y = (int) midPos.getOrdinate(1); int halfWidth = CACHED_RASTER_WIDTH / 2; final Rectangle queryRect = new Rectangle( x - halfWidth, y - halfWidth, CACHED_RASTER_WIDTH, CACHED_RASTER_WIDTH); GridEnvelope gridEnv = reader.getOriginalGridRange(); Rectangle rect = new Rectangle( gridEnv.getLow(0), gridEnv.getLow(1), gridEnv.getSpan(0), gridEnv.getSpan(1)); XRectangle2D.intersect(queryRect, rect, queryRect); return queryRect; } catch (Exception ex) { throw new RuntimeException(ex); } } }