/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2009-2011, 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.ext.isoline.graphic; import com.vividsolutions.jts.geom.Coordinate; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import org.apache.sis.feature.FeatureExt; import org.geotoolkit.coverage.grid.GridCoverage2D; import org.geotoolkit.data.FeatureStoreRuntimeException; import org.geotoolkit.data.FeatureCollection; import org.geotoolkit.data.FeatureIterator; import org.geotoolkit.display.canvas.control.CanvasMonitor; import org.geotoolkit.display.PortrayalException; import org.geotoolkit.display2d.GO2Utilities; import org.geotoolkit.display2d.canvas.J2DCanvas; import org.geotoolkit.display2d.canvas.RenderingContext2D; import org.geotoolkit.display2d.container.stateless.StatelessCoverageLayerJ2D; import org.geotoolkit.display2d.container.stateless.StatelessFeatureLayerJ2D; import org.apache.sis.geometry.GeneralDirectPosition; import org.apache.sis.geometry.GeneralEnvelope; import org.geotoolkit.map.CoverageMapLayer; import org.geotoolkit.map.FeatureMapLayer; import org.geotoolkit.map.MapBuilder; import org.geotoolkit.parameter.Parameters; import org.geotoolkit.process.Process; import org.geotoolkit.process.ProcessDescriptor; import org.geotoolkit.process.ProcessEvent; import org.geotoolkit.process.ProcessException; import org.geotoolkit.process.ProcessListener; import org.geotoolkit.processing.ProcessListenerAdapter; import org.geotoolkit.processing.coverage.kriging.KrigingDescriptor; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.style.MutableStyle; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.Envelope; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.TransformException; import org.apache.sis.geometry.Envelopes; import org.opengis.feature.Feature; /** * * @author Sorel Johann (Geomatys) * @module */ public class IsolineGraphicJ2D extends StatelessFeatureLayerJ2D { private final ValueExtractor extractor; private MutableStyle isoPointStyle = null; private MutableStyle isoLineStyle = null; private MutableStyle coverageStyle = null; private boolean interpolateCoverageColor = true; private int step = 10; public IsolineGraphicJ2D(final J2DCanvas canvas, final FeatureMapLayer layer, final ValueExtractor extractor) { super(canvas, layer); this.extractor = extractor; } public void setStep(final int step) { this.step = step; } public double getStep() { return step; } public void setCoverageStyle(final MutableStyle coverageStyle) { this.coverageStyle = coverageStyle; } public void setIsoLineStyle(final MutableStyle isoLineStyle) { this.isoLineStyle = isoLineStyle; } public void setIsoPointStyle(final MutableStyle isoPointStyle) { this.isoPointStyle = isoPointStyle; } public MutableStyle getCoverageStyle() { return coverageStyle; } public MutableStyle getIsoLineStyle() { return isoLineStyle; } public MutableStyle getIsoPointStyle() { return isoPointStyle; } public void setInterpolateCoverageColor(final boolean interpolateCoverageColor) { this.interpolateCoverageColor = interpolateCoverageColor; } public boolean isInterpolateCoverageColor() { return interpolateCoverageColor; } @Override public void paintLayer(final RenderingContext2D context) { //we abort painting if the layer is not visible. if (!item.isVisible()) { return; } final CanvasMonitor monitor = context.getMonitor(); final Graphics2D g2 = context.getGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g2.setComposite(GO2Utilities.ALPHA_COMPOSITE_1F); FeatureCollection collection = item.getCollection(); try { collection = collection.subCollection(item.getQuery()); } catch (DataStoreException ex) { monitor.exceptionOccured(ex, Level.WARNING); return; } double minx = Double.NaN; double miny = Double.NaN; double maxx = Double.NaN; double maxy = Double.NaN; try { final List<DirectPosition> coordinates = new ArrayList<>(); final FeatureIterator iterator = collection.iterator(); try { while (iterator.hasNext()) { final Feature feature = iterator.next(); final Coordinate coord = extractor.getValues(context, feature); if(coord == null) continue; final GeneralDirectPosition pos = new GeneralDirectPosition(coord.x, coord.y, coord.z); coordinates.add(pos); minx = Double.isNaN(minx) ? coord.x : Math.min(minx, coord.x); maxx = Double.isNaN(maxx) ? coord.x : Math.max(maxx, coord.x); miny = Double.isNaN(miny) ? coord.y : Math.min(miny, coord.y); maxy = Double.isNaN(maxy) ? coord.y : Math.max(maxy, coord.y); } }catch(Exception ex){ monitor.exceptionOccured(ex, Level.WARNING); return; }finally { iterator.close(); } if(coordinates.isEmpty()){ //nothing to render return; } final CoordinateReferenceSystem crs = FeatureExt.getCRS(collection.getFeatureType()); final GeneralEnvelope env = new GeneralEnvelope(crs); env.setRange(0, minx, maxx); env.setRange(1, miny, maxy); final Envelope objenv = Envelopes.transform(env, context.getObjectiveCRS2D()); final double[] res = context.getResolution(); if(objenv.getSpan(0) <= res[0]*8 || objenv.getSpan(1) <= res[1]*8){ //envelope is too small, do not paint return; } final ProcessListener redirect = new ProcessListenerAdapter(){ @Override public void failed(ProcessEvent event) { if(event.getException() != null){ monitor.exceptionOccured((Exception)event.getException(), Level.WARNING); } } @Override public void progressing(ProcessEvent event) { if(event.getException() != null){ monitor.exceptionOccured((Exception)event.getException(), Level.WARNING); } } }; final ProcessDescriptor desc = KrigingDescriptor.INSTANCE; final ParameterValueGroup input = desc.getInputDescriptor().createValue(); Parameters.getOrCreate(KrigingDescriptor.IN_POINTS, input) .setValue(coordinates.toArray(new DirectPosition[coordinates.size()])); Parameters.getOrCreate(KrigingDescriptor.IN_CRS, input) .setValue(crs); Parameters.getOrCreate(KrigingDescriptor.IN_STEP, input) .setValue(step); Parameters.getOrCreate(KrigingDescriptor.IN_DIMENSION, input) .setValue(new Dimension(150, 150)); final Process p = desc.createProcess(input); p.addListener(redirect); final ParameterValueGroup output; try { output = p.call(); } catch (ProcessException ex) { getLogger().log(Level.WARNING, null, ex); return; } final GridCoverage2D coverage = Parameters.value(KrigingDescriptor.OUT_COVERAGE, output); final FeatureCollection isolines = Parameters.value(KrigingDescriptor.OUT_LINES, output); if(coverage != null){ if(interpolateCoverageColor){ //paint with the black and white palette try { GO2Utilities.portray(context, coverage); } catch (PortrayalException ex) { context.getMonitor().exceptionOccured(ex, Level.WARNING); return; } }else if(coverageStyle != null){ //paint with the style final CoverageMapLayer covlayer = MapBuilder.createCoverageLayer(coverage, coverageStyle, "test"); final StatelessCoverageLayerJ2D graphic = new StatelessCoverageLayerJ2D(getCanvas(), covlayer); graphic.paint(context); } } if(isolines != null && isoLineStyle != null){ final FeatureMapLayer flayer = MapBuilder.createFeatureLayer(isolines, isoLineStyle); final StatelessFeatureLayerJ2D graphic = new StatelessFeatureLayerJ2D(getCanvas(), flayer); graphic.paint(context); } } catch (TransformException ex) { getLogger().log(Level.WARNING, null, ex); } catch (FeatureStoreRuntimeException ex) { getLogger().log(Level.WARNING, null, ex); } } }