All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.cloudfarming.client.geoviewer.render.GridCoverage2DRenderer Maven / Gradle / Ivy

Go to download

AgroSense geoviewer render - contains classes for rendering of various geo objects

The newest version!
/**
 * Copyright (C) 2008-2012 AgroSense Foundation.
 *
 * AgroSense is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * There are special exceptions to the terms and conditions of the GPLv3 as it is applied to
 * this software, see the FLOSS License Exception
 * .
 *
 * AgroSense 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AgroSense.  If not, see .
 */
package nl.cloudfarming.client.geoviewer.render;

import com.vividsolutions.jts.geom.*;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import nl.cloudfarming.client.geoviewer.Grid;
import nl.cloudfarming.client.geoviewer.Palette;
import nl.cloudfarming.client.geoviewer.ValueRange;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.ViewType;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.filter.expression.ExpressionAbstract;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.renderer.lite.gridcoverage2d.GridCoverageRenderer;
import org.geotools.styling.*;
import org.netbeans.api.visual.model.ObjectState;
import org.opengis.filter.expression.ExpressionVisitor;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException;
import org.openide.util.Exceptions;

/**
 * GridCoverage2DRenderer
 *
 *
 * @author Timon Veenstra
 */
public class GridCoverage2DRenderer implements RasterRenderer {

    private static final Color EMPTY_COLOR = new Color(0.0f, 0.0f, 0.0f);
    private static final float OPACITY_HOVER = (float) Palette.ALPHA_HOVER / 255;
    private static final float OPACITY_SELECTED = (float) Palette.ALPHA_SELECTED / 255;
    private static final float OPACITY_NORMAL = (float) Palette.ALPHA_NORMAL / 255;

    /**
     * this gets rid of exception for not using native acceleration
     */
    static {
        System.setProperty("com.sun.media.jai.disableMediaLib", "true");
    }
    private StyleFactory sf = CommonFactoryFinder.getStyleFactory(null);

    @Override
    public void paint(GridCoverage2D raster, Rectangle viewport, Graphics2D graphics, Palette palette, ObjectState state, GeoTranslator translator) {
        // skip painting is raster is empty
        if (raster == null) {
            return;
        }
        
        int numBands = raster.getNumSampleDimensions();
        if (numBands > 1) {
            // can't apply a ColorMap to a multiband coverage (org.geotools.renderer.lite.gridcoverage2d.ColorMapNode:150)
            return;
        }

        try {
            ReferencedEnvelope rasterEnvelope = new ReferencedEnvelope(raster.getEnvelope2D());
            rasterEnvelope = rasterEnvelope.transform(DefaultGeographicCRS.WGS84, true);
            Rectangle bounds = getBounds(rasterEnvelope, viewport, translator);
            GridCoverageRenderer renderer = new GridCoverageRenderer(DefaultGeographicCRS.WGS84, rasterEnvelope, bounds, (AffineTransform) null);
            RasterSymbolizer symbolizer = sf.getDefaultRasterSymbolizer();
            if (state.isHovered() || state.isObjectHovered()) {
                symbolizer.setOpacity(new OpacityExp(OPACITY_HOVER));
            } else if (state.isSelected()) {
                symbolizer.setOpacity(new OpacityExp(OPACITY_SELECTED));
            } else {
                symbolizer.setOpacity(new OpacityExp(OPACITY_NORMAL));
            }
            if (palette instanceof ValueRange) {
                ValueRange range = (ValueRange) palette;
                Number min = (range.getMinValue() == null ? 0 : range.getMinValue());
                Number max = (range.getMaxValue() == null ? 0 : range.getMaxValue());
                ColorMapEntry entry = getEntry(EMPTY_COLOR, Grid.EMPTY_VALUE);
                entry.setOpacity(new OpacityExp(0.0f));
                symbolizer.getColorMap().addColorMapEntry(entry);
                
                if (min.equals(max)) {
                    // add single value
                    Color c = palette.getColorForValue(min);
                    ColorMapEntry singleEntry = getEntry(c, min.doubleValue());
                    symbolizer.getColorMap().addColorMapEntry(singleEntry);
                } else {
                    int nColors = range.getSteps();
                    double step = (max.doubleValue() - min.doubleValue()) / (nColors - 1);
                    for (int s = 0; s < nColors; s++) {
                        Double value = min.doubleValue() + (s * step);
                        Color c = palette.getColorForValue(value); // FIXME: depends on the Palette implementation using Number as the generic type (and not the subclass used by the ValueRange implementation)
                        symbolizer.getColorMap().addColorMapEntry(getEntry(c, value));
                    }
                }

            } else {
                //
                //fallback
                //
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFF000000, true), 1));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFF8F050C, true), 100));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFFDB0F01, true), 200));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFFE65E00, true), 300));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFFFC9F00, true), 400));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFFFAD007, true), 500));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFFDCF40A, true), 600));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFF92FC00, true), 700));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFF41C405, true), 800));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFF048608, true), 900));
                symbolizer.getColorMap().addColorMapEntry(getEntry(new Color(0xFF044606, true), 1000));
            }
            symbolizer.getColorMap().setType(ColorMap.TYPE_RAMP);

            renderer.paint(graphics, raster.view(ViewType.GEOPHYSICS), symbolizer);
        } catch (FactoryException ex) {
            Exceptions.printStackTrace(ex);
        } catch (TransformException ex) {
            Exceptions.printStackTrace(ex);
        } catch (NoninvertibleTransformException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    private ColorMapEntry getEntry(Color color, double value) {
        ColorMapEntry entry = new ColorMapEntryImpl();
        entry.setColor(new ColorExp(color));
        entry.setQuantity(new ValueExp(value));
        return entry;
    }

    private class ColorExp extends ExpressionAbstract {

        private final Color color;

        public ColorExp(Color color) {
            this.color = color;
        }

        @Override
        public Object evaluate(Object object) {
            return this.color;
        }

        @Override
        public Object accept(ExpressionVisitor visitor, Object extraData) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    private class ValueExp extends ExpressionAbstract {

        private final double value;

        public ValueExp(double value) {
            this.value = value;
        }

        @Override
        public Object evaluate(Object object) {
            return Double.valueOf(this.value);
        }

        @Override
        public Object accept(ExpressionVisitor visitor, Object extraData) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    private class OpacityExp extends ExpressionAbstract {

        private final double opacity;

        public OpacityExp(double opacity) {
            assert opacity <= 1.0 && opacity >= 0.0;
            this.opacity = opacity;
        }

        @Override
        public Object evaluate(Object object) {
            return new Double(this.opacity);
        }

        @Override
        public Object accept(ExpressionVisitor visitor, Object extraData) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
    
    private Rectangle getBounds(Envelope envelope, Rectangle viewport, GeoTranslator translator) {
        Geometry geometry = JTS.toGeometry(envelope);
        final Point2D upLeft = translator.geoToPixel(viewport, geometry, new Coordinate(envelope.getMinX(), envelope.getMinY()));
        final Point2D downRight = translator.geoToPixel(viewport, geometry, new Coordinate(envelope.getMaxX(), envelope.getMaxY()));
        Rectangle bounds = new Rectangle((int) (upLeft.getX() - viewport.getX()), (int) (upLeft.getY() - viewport.getY()), 0, 0);
        bounds.add((int) (downRight.getX() - viewport.getX()), (int) (downRight.getY() - viewport.getY()));
        return bounds;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy