Package org.locationtech.udig.render.internal.gridcoverage.basic

Source Code of org.locationtech.udig.render.internal.gridcoverage.basic.MemoryGridCoverageRenderer

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2004-2012, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.render.internal.gridcoverage.basic;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.util.Collections;

import javax.media.jai.InterpolationNearest;
import javax.media.jai.JAI;
import javax.media.jai.TileCache;

import org.locationtech.udig.catalog.IGeoResource;
import org.locationtech.udig.catalog.rasterings.GridCoverageLoader;
import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.project.internal.ProjectPlugin;
import org.locationtech.udig.project.internal.StyleBlackboard;
import org.locationtech.udig.project.internal.render.impl.RendererImpl;
import org.locationtech.udig.project.render.IRenderContext;
import org.locationtech.udig.project.render.RenderException;
import org.locationtech.udig.project.render.displayAdapter.IMapDisplay;
import org.locationtech.udig.render.gridcoverage.basic.internal.Messages;
import org.locationtech.udig.ui.graphics.SLDs;

import org.eclipse.core.runtime.IProgressMonitor;
import org.geotools.coverage.CoverageFactoryFinder;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.image.ImageWorker;
import org.geotools.referencing.CRS;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.geotools.renderer.lite.RendererUtilities;
import org.geotools.renderer.lite.gridcoverage2d.GridCoverageRenderer;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.RasterSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.filter.expression.Expression;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;

/**
* Render raster information from memory.
* <p>
* This renderer is expensive in terms of memory but is the best choice for formats
* such as jpeg which are not optimised for crop operation (ie you need
* to read in the entire image to draw even a small part of it).
* <p>
* Initially the rendering system looks at the style for:
* <ul>
* <li>scale ranges (handled in the rendering metrics)</li>
* <li>opacity</li>
* </ul>
* Now that raster symbolizer support is available in GeoTools we may be able to do better
* and handle things like color maps?
* @see GridCoverageLoader
* @author Jesse Eichar
* @author Andrea Aime
* @version $Revision: 1.9 $
*/
public class MemoryGridCoverageRenderer extends RendererImpl {
    /**
     * Internal GridCoverageRenderer used to perform the drawing
     * (chances are we could use the normal streaming renderer here
     *  and perform a bit better?)
     */
    private GridCoverageRenderer renderer;
   
    /**
     * Renderer using a GridCoverageLoader to render out of memory
     * (used to load jpeg into memory; or can be used when user requests cache)
     */
    public MemoryGridCoverageRenderer(){       
    }
    @SuppressWarnings("unchecked")
  public synchronized void render( Graphics2D graphics, IProgressMonitor monitor )
            throws RenderException {
        try {
          // get the current context
          final IRenderContext currentContext = getContext();        
         
          //check that actually we have something to draw
            currentContext.setStatus(ILayer.WAIT);
            currentContext.setStatusMessage(Messages.BasicGridCoverageRenderer_rendering_status);
           
            //get the envelope and the screen extent
            ReferencedEnvelope envelope = getRenderBounds();
            if( envelope == null || envelope.isNull()){
                envelope = context.getImageBounds();
            }
            Point upperLeft = currentContext.worldToPixel( new Coordinate( envelope.getMinX(), envelope.getMinY()) );
            Point bottomRight = currentContext.worldToPixel( new Coordinate( envelope.getMaxX(), envelope.getMaxY()) );
            Rectangle screenSize = new Rectangle( upperLeft );
            screenSize.add( bottomRight );
          IMapDisplay mapDisplay = currentContext.getMapDisplay();
           
          CoordinateReferenceSystem destinationCRS = currentContext.getCRS();

            final IGeoResource geoResource = currentContext.getGeoResource();
            ReferencedEnvelope bounds = (ReferencedEnvelope) currentContext.getImageBounds();
            bounds=bounds.transform(destinationCRS, true);
           
            GridEnvelope range=new GridEnvelope2D(0,0, mapDisplay.getWidth(), mapDisplay.getHeight() );
           
            MathTransform displayToLayer=currentContext.worldToScreenMathTransform().inverse();
            ReferencingFactoryFinder.getMathTransformFactory(null).createConcatenatedTransform(displayToLayer, currentContext.getLayer().mapToLayerTransform());
            GridGeometry2D geom=new GridGeometry2D(range, displayToLayer, destinationCRS );

            currentContext.setStatus(ILayer.WORKING);
            setState( STARTING );
           
            GridCoverageLoader loader = geoResource.resolve(GridCoverageLoader.class, monitor);
            if( loader == null ){
                // unable to load in memory
                return;
            }
            GridCoverage2D coverage = (GridCoverage2D) loader.load(geom, monitor);

            if(coverage!=null)
      {
             
              //setting rendering hints
              RenderingHints hints = new RenderingHints(Collections.EMPTY_MAP);
              hints.add(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED));
              hints.add(new RenderingHints(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE));
              hints.add(new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED));
              hints.add(new RenderingHints(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED));
              hints.add(new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR));
              hints.add(new RenderingHints(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE));
              hints.add(new RenderingHints(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF));
              hints.add(new RenderingHints(JAI.KEY_INTERPOLATION,new InterpolationNearest()));
              graphics.addRenderingHints(hints);
             
              final TileCache tempCache=currentContext.getTileCache();
              hints.add(new RenderingHints(JAI.KEY_TILE_CACHE,tempCache));
             
              if( CRS.getHorizontalCRS(destinationCRS) == null ){
                  destinationCRS = coverage.getCoordinateReferenceSystem2D();
              }
              //draw
              try {
                  Style style = grabStyle();
                  Rule rule = SLDs.getRasterSymbolizerRule(style);
                 
                  final double currentScale = currentContext.getViewportModel().getScaleDenominator();               
                  double minScale = rule.getMinScaleDenominator();
                  double maxScale = rule.getMaxScaleDenominator();
                  if (minScale <= currentScale && currentScale <= maxScale ) {
                      final GridCoverageRenderer paint = new GridCoverageRenderer( destinationCRS, envelope, screenSize,null, hints );
                      final RasterSymbolizer rasterSymbolizer = SLD.rasterSymbolizer(style);
                 
                        // check if there is a color to mask
                        Object maskColor = getContext().getLayer().getStyleBlackboard().getString("raster-color-mask"); //$NON-NLS-1$                      
                        if (maskColor instanceof String) {
                            // create a color mask
                            String[] colorSplit = ((String) maskColor).split(":"); //$NON-NLS-1$
                            Color color = new Color(Integer.parseInt(colorSplit[0]), Integer.parseInt(colorSplit[1]),
                                    Integer.parseInt(colorSplit[2]));
                            RenderedImage image = coverage.getRenderedImage();
                            ImageWorker iw = new ImageWorker(image);
                            iw.makeColorTransparent(color);
                            image = iw.getRenderedImage();
                            GridCoverageFactory gcF = CoverageFactoryFinder.getGridCoverageFactory(null);
                            coverage = gcF.create(coverage.getName(), image, coverage.getCoordinateReferenceSystem(), coverage
                                    .getGridGeometry().getGridToCRS(), coverage.getSampleDimensions(), null, null);
                        }
                     
                      //setState( RENDERING );
                      paint.paint( graphics, coverage, rasterSymbolizer );                       
                      setState( DONE );
                  }
                 
              } catch(Exception e) {
                  final GridCoverageRenderer paint = new GridCoverageRenderer( destinationCRS, envelope, screenSize,null, hints );
                  RasterSymbolizer rasterSymbolizer = CommonFactoryFinder.getStyleFactory(null).createRasterSymbolizer();
                 
                  //setState( RENDERING );
                  paint.paint( graphics, coverage, rasterSymbolizer );
                    setState( DONE );
              }
              //tempCache.flush();
      }
        } catch (Exception e1) {
            throw new RenderException(e1);
        }
        finally {
            getContext().setStatus(ILayer.DONE);
            getContext().setStatusMessage(null);
        }
    }

    /**
     *  grab the style from the blackboard, otherwise return null
     */
    private Style grabStyle() {
        // check for style information on the blackboard
        StyleBlackboard styleBlackboard = (StyleBlackboard) getContext()
                .getLayer().getStyleBlackboard();
       
        Style style = (Style) styleBlackboard.lookup(Style.class);
       
        return style;
    }
    /*
    public synchronized void render2( Graphics2D graphics, IProgressMonitor monitor )
            throws RenderException {
        State state = null;
        try {
            state = prepareRender(monitor);
        } catch (IOException e1) {
            throw new RenderException(e1);
        }

        doRender(renderer, graphics, state);
    }*/
    /**
     * Renders a GridCoverage
     *
     * @param renderer
     * @param graphics
     */
    public void doRender( GridCoverageRenderer renderer, Graphics2D graphics, GridCoverageRenderState state ) {
        double scale = state.context.getViewportModel().getScaleDenominator();
        if (scale < state.minScale || scale > state.maxScale)
            return;

        state.context.setStatus(ILayer.WAIT);
        state.context.setStatusMessage(Messages.BasicGridCoverageRenderer_rendering_status);

        // setup composite
        Composite oldComposite = graphics.getComposite();
        graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, state.opacity));

        // setup affine transform for on screen rendering
        Rectangle displayArea = state.displayArea;

        AffineTransform at = RendererUtilities.worldToScreenTransform(state.bounds, displayArea);
        AffineTransform tempTransform = graphics.getTransform();
        AffineTransform atg = new AffineTransform(tempTransform);
        atg.concatenate(at);
        graphics.setTransform(atg);

        GridCoverage coverage;
        try {
            coverage = getContext().getGeoResource().resolve(GridCoverage.class, null);

            RasterSymbolizer rasterSymbolizer;

            StyleFactory factory = CommonFactoryFinder.getStyleFactory(null);
            rasterSymbolizer = factory.createRasterSymbolizer();

            renderer.paint(graphics, (GridCoverage2D) coverage, rasterSymbolizer);
        } catch (IOException e) {
            // TODO Handle IOException
            throw (RuntimeException) new RuntimeException().initCause(e);
        } catch (FactoryException e) {
            throw (RuntimeException) new RuntimeException().initCause(e);
        } catch (TransformException e) {
            throw (RuntimeException) new RuntimeException().initCause(e);
        } catch (NoninvertibleTransformException e) {
            throw (RuntimeException) new RuntimeException().initCause(e);
        }

        // reset previous configuration
        graphics.setComposite(oldComposite);
        graphics.setTransform(tempTransform);

        if (state.context.getStatus() == ILayer.WAIT) {
            // status hasn't changed... everything looks good
            state.context.setStatus(ILayer.DONE);
            state.context.setStatusMessage(null);
        }

    }

    /**
     * Extract symbolizer parameters from the style blackboard
     */
    public static GridCoverageRenderState getRenderState( IRenderContext context ) {
        StyleBlackboard styleBlackboard = (StyleBlackboard) context.getLayer().getStyleBlackboard();
        Style style = (Style) styleBlackboard.lookup(Style.class);
        double minScale = Double.MIN_VALUE;
        double maxScale = Double.MAX_VALUE;
        float opacity = 1.0f;
        if (style != null) {
            try {
                FeatureTypeStyle featureStyle = style.featureTypeStyles().get(0);               
                Rule rule = featureStyle.rules().get(0);
                minScale = rule.getMinScaleDenominator();
                maxScale = rule.getMaxScaleDenominator();
                if (rule.getSymbolizers()[0] instanceof RasterSymbolizer) {
                    RasterSymbolizer rs = (RasterSymbolizer) rule.getSymbolizers()[0];
                    opacity = getOpacity(rs);
                }

            } catch (Exception e) {
                ProjectPlugin.getPlugin().log(e);
            }
        } else {
            opacity = 1;
            minScale = 0;
            maxScale = Double.MAX_VALUE;
        }

        Rectangle displayArea = new Rectangle(context.getMapDisplay().getWidth(), context
                .getMapDisplay().getHeight());

        return new GridCoverageRenderState(context, context.getImageBounds(), displayArea, opacity,
                minScale, maxScale);
    }

    private static float getOpacity( RasterSymbolizer sym ) {
        float alpha = 1.0f;
        Expression exp = sym.getOpacity();
        if (exp == null)
            return alpha;
        Object obj = exp.evaluate(null);
        if (obj == null)
            return alpha;
        Number num = null;
        if (obj instanceof Number)
            num = (Number) obj;
        if (num == null)
            return alpha;
        return num.floatValue();
    }

    private GridCoverageRenderState prepareRender( IProgressMonitor monitor ) throws IOException {

        try {
            CoordinateReferenceSystem contextCRS = getContext().getCRS();
            Rectangle rectangle = new Rectangle(getContext().getMapDisplay().getDisplaySize());
            Envelope bounds = getRenderBounds();
            if (bounds == null) {
                // show the bounds of the context
                bounds = getContext().getImageBounds();
                if (bounds instanceof ReferencedEnvelope) {
                    ReferencedEnvelope all = (ReferencedEnvelope) bounds;
                    if (!contextCRS.equals(all.getCoordinateReferenceSystem())) {
                        bounds = all.transform(contextCRS, true, 10);
                    }
                } else {
                    // this should not happen!
                    ReferencedEnvelope all = new ReferencedEnvelope(bounds, getContext()
                            .getViewportModel().getCRS());
                    bounds = all.transform(contextCRS, true, 10);
                }
            }
            AffineTransform world2screen = null;
            renderer = new GridCoverageRenderer(contextCRS, bounds, rectangle,world2screen);

        } catch (TransformException e) {
            // TODO Handle TransformException
            throw (RuntimeException) new RuntimeException().initCause(e);
        } catch (NoninvertibleTransformException e) {
            // TODO Handle NoninvertibleTransformException
            throw (RuntimeException) new RuntimeException().initCause(e);
        } catch (FactoryException e) {
            // TODO Handle FactoryException
            throw (RuntimeException) new RuntimeException().initCause(e);
        }
        return getRenderState(getContext());
    }

    public void stopRendering() {
        setState(STATE_EDEFAULT);
    }

    public void dispose() {
        // TODO
    }

    public void render( IProgressMonitor monitor ) throws RenderException {
        render(getContext().getImage().createGraphics(), monitor);
    }

}
TOP

Related Classes of org.locationtech.udig.render.internal.gridcoverage.basic.MemoryGridCoverageRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.