view gnv-artifacts/src/main/java/de/intevation/gnv/chart/VerticalProfileChartFactory.java @ 327:22a6493e8460

New options in chart template: visibility of lines and points in charts and point's size. gnv-artifacts/trunk@393 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 02 Dec 2009 10:50:12 +0000
parents 3d6d89bcbf42
children e964a3d8f7bc
line wrap: on
line source
/**
 * Title:           ChartFactory, $Header: /share/gdi/SDI-Suite/Repository/projekte/BSH-GDI/genericViewer/src/main/java/de/conterra/bsh/gdi/gnviewer/output/chart/ChartFactory.java,v 1.8 2007/12/21 12:31:15 blume Exp $
 * Source:          $Source: /share/gdi/SDI-Suite/Repository/projekte/BSH-GDI/genericViewer/src/main/java/de/conterra/bsh/gdi/gnviewer/output/chart/ChartFactory.java,v $
 * created by:      Stefan Blume (blume)
 * erstellt am:     06.12.2007
 * Copyright:       con terra GmbH, 2005
 *
 * modified by:     $Author: blume $
 * modified on:     $Date: 2007/12/21 12:31:15 $
 * Version:         $Revision: 1.8 $
 * TAG:             $Name:  $
 * locked from:     $Locker:  $
 * CVS State:       $State: Exp $
 * Project:         $ProjectName$
 */
package de.intevation.gnv.chart;

import java.awt.Color;
import java.awt.Font;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Iterator;

import org.apache.log4j.Logger;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.encoders.KeypointPNGEncoderAdapter;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleInsets;

import de.intevation.gnv.chart.exception.TechnicalChartException;
import de.intevation.gnv.geobackend.base.Result;
import de.intevation.gnv.transition.describedata.KeyValueDescibeData;

/**
 * 
 * @author Tim Englich <tim.englich@intevation.de>
 * 
 */
public class VerticalProfileChartFactory {

    /**
     * Default Logging instance
     */
    private static Logger sLogger = Logger
            .getLogger(VerticalProfileChartFactory.class);
    private static boolean sDebug = sLogger.isDebugEnabled();
    protected PlotOrientation plotOrientation = PlotOrientation.HORIZONTAL;

    public synchronized void createProfileChart(
                                                ChartLabels pLabels,
                                                ChartStyle pStyle,
                                                Collection<KeyValueDescibeData> parameters,
                                                Collection<KeyValueDescibeData> measurements,
                                                Collection<KeyValueDescibeData> dates,
                                                OutputStream outputStream,
                                                Collection<Result> resultSet)
                                                                             throws IOException,
                                                                             TechnicalChartException {
        if (sDebug)
            sLogger.debug("createSimpleTimeSeriesChart()");
        int lLowerLevel = Integer.MIN_VALUE;
        int lUpperLevel = Integer.MAX_VALUE;
        if (pStyle.isUseUpperDataLevel()
            && pStyle.getUpperLevel() < Integer.MAX_VALUE) {
            lUpperLevel = pStyle.getUpperLevel();
        }
        if (pStyle.isUseLowerDataLevel()
            && pStyle.getLowerLevel() > Integer.MIN_VALUE) {
            lLowerLevel = pStyle.getLowerLevel();
        }
        if (sDebug)
            sLogger.debug("  vor createDataset()");
        XYDataset lSet = this.createDataset(resultSet, lUpperLevel,
                lLowerLevel, parameters, measurements, dates);
        if (sDebug)
            sLogger.debug("  nach createDataset()");
        final Color[] color = { Color.black, Color.red, Color.green, Color.blue };
        NumberAxis domain = new NumberAxis(pLabels.getDomainAxisLabel());
        NumberAxis axis;
        StandardXYItemRenderer renderer = new StandardXYItemRenderer();
        XYPlot plot = new XYPlot();
        // Global settings

        plot.setOrientation(plotOrientation);
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        // plot.getRangeAxis().setFixedDimension(10.0);
        plot.setDomainAxis(domain);
        plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
        if (parameters.size() == 1) {
            KeyValueDescibeData parameter = parameters.iterator().next();
            axis = new NumberAxis(parameter.getValue());
            if (parameter.getValue().contains("richtung")) {
                NumberAxis axis1 = new NumberAxis((parameter
                        .getValue()));// ,new Range(0.0,360.0));
                axis1.setTickUnit(new NumberTickUnit(30.0));
                axis1.setUpperBound(360.0);
                axis1.setLowerBound(0.0);
                // axis1.setDisplayRange(0.0,360.0);
                plot.setRangeAxis(axis1);
            } else {
                axis.setFixedDimension(10.0);
                axis.setAutoRangeIncludesZero(false);
                plot.setRangeAxis(axis);
            }
            axis.configure();
            plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
            plot.setRenderer(renderer);
            plot.setDataset(lSet);
        } else {
            // Individual settings for different parameters
            for (int i = 0; i < lSet.getSeriesCount(); i++) {

                plot.setDataset(i, getDataset((XYSeriesCollection) lSet, i));
                Color mColor = color[i % color.length]; // zyklische Farbvergabe
                mColor = color[0];
                // if ( pParameterId.length==1){

                if (((String) lSet.getSeriesKey(i)).contains("richtung")) {
                    NumberAxis axis1 = new NumberAxis(((String) lSet
                            .getSeriesKey(i)));// ,new Range(0.0,360.0));
                    axis1.setTickUnit(new NumberTickUnit(30.0));
                    // axis1.setDisplayRange(0.0,360.0);
                    axis1.setLabelPaint(mColor);
                    axis1.setTickLabelPaint(mColor);
                    axis1.setUpperBound(360.0);
                    axis1.setLowerBound(0.0);
                    plot.setRangeAxis(i, axis1);

                } else {
                    axis = new NumberAxis((String) lSet.getSeriesKey(i));
                    axis.setFixedDimension(10.0);
                    axis.setAutoRangeIncludesZero(false);
                    axis.setLabelPaint(mColor);
                    axis.setTickLabelPaint(mColor);
                    plot.setRangeAxis(i, axis);
                    axis.configure();
                }
                if (i % 2 != 0)
                    plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_RIGHT);
                else
                    plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_LEFT);
                plot.mapDatasetToRangeAxis(i, i);
                // }
                renderer = new StandardXYItemRenderer();
                renderer.setSeriesPaint(i, mColor);
                // renderer.setSeriesStroke(i,stroke[j]);
                plot.setRenderer(i, renderer);
            }
        }
        JFreeChart chart = new JFreeChart(pLabels.getTitle(), new Font(
                "SansSerif", Font.BOLD, 24), plot, true);

        setStyle(chart, pStyle);
        configureRenderingOptions(chart);
        if (sDebug)
            sLogger.debug("  vor encodeChart()");

        encodeChart(chart, pStyle, outputStream);
    }

    private static XYDataset getDataset(XYSeriesCollection T, int pIndex) { // throws
                                                                            // TechnicalChartException{
        // if (T.getSeriesCount() < pIndex) throw TechnicalChartException();
        XYSeriesCollection XYSC = new XYSeriesCollection();
        XYSC.addSeries(T.getSeries(pIndex));
        return XYSC;
    }

    private void configureRenderingOptions(JFreeChart pJfreechart) {
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = ((XYPlot) pJfreechart
                .getPlot()).getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
        }
    }

    private void setStyle(JFreeChart pJfreechart, ChartStyle pStyle) {
        if (sDebug)
            sLogger.debug("setStyle()");
        pJfreechart.setBackgroundPaint(pStyle.getCanvasColor());
        XYPlot xyplot = (XYPlot) pJfreechart.getPlot();
        xyplot.setBackgroundPaint(pStyle.getPlotBackgroundColor());
        xyplot.setDomainGridlinePaint(pStyle.getDomainGridlineColor());
        xyplot.setRangeGridlinePaint(pStyle.getRangeGridlineColor());

        Insets lOffsets = pStyle.getAxisOffset();
        RectangleInsets lRectangleInsets = new RectangleInsets(lOffsets.mUpper,
                lOffsets.mLeft, lOffsets.mLower, lOffsets.mRight);
        xyplot.setAxisOffset(lRectangleInsets);
        xyplot.setDomainCrosshairVisible(pStyle.isDomainCrosshairVisible());
        xyplot.setRangeCrosshairVisible(pStyle.isRangeCrosshairVisible());

    }

    protected XYSeries createXYSeries(String seriesName,
                                      Collection<Result> resultSet,
                                      int lUpperCut, int lLowerCut, int pStart,
                                      int pEnd, double maxGap) throws TechnicalChartException {
        if (sDebug)
            sLogger.debug("createXYSeries()");
        XYSeries series = new XYSeries(seriesName);
        try {
            double xValue = 0;
            double yValue = 0;
            int i = 0;
            Iterator<Result> resultIterator = resultSet.iterator();
            while (resultIterator.hasNext()) {
                Result lRow = resultIterator.next();
                if (i >= pStart && i <= pEnd) {
                    xValue = lRow.getDouble("XORDINATE");
                    yValue = lRow.getDouble("YORDINATE");
                    series.add(xValue, yValue);
                    sLogger.debug(seriesName + " Added Value " + xValue + " / "
                                  + yValue);

                } else if (i > pEnd) {
                    return series;
                }
                i++;
            }
        } catch (OutOfMemoryError e) {
            sLogger.error(e.getMessage(), e);
            return series;

        } catch (Exception e) { // TechnicalChartException
            sLogger.error(e.getMessage(), e);
        } finally {
        }

        return series;
    }

    private XYDataset createDataset(Collection<Result> resultSet,
                                    int lUpperCut, int lLowerCut,
                                    Collection<KeyValueDescibeData> parameters,
                                    Collection<KeyValueDescibeData> measurements,
                                    Collection<KeyValueDescibeData> dates)
                                                                                 throws TechnicalChartException {

        XYSeriesCollection xyDataset = new XYSeriesCollection();

        try {
            String break1, break2, break3;
            int mStart = 0;
            int mEnd = 0;

            Iterator<Result> resultIterator = resultSet.iterator();
            Result firstRow = null, lastRow = null;
            
            double maxGap;
            if (resultIterator.hasNext()) {
                // Row row = new Row(sArrayStrLine);
                Result row = resultIterator.next();
                
                firstRow = row;
                lastRow = row;
                
                break1 = row.getString("GROUP1"); // 2
                break2 = row.getString("GROUP2"); // 3
                break3 = row.getString("GROUP3"); // 4
                int i = 1;
                while (resultIterator.hasNext()) {
                    row = resultIterator.next();
                    
                    if (!break1.equals(row.getString("GROUP1"))
                        || !break2.equals(row.getString("GROUP2"))
                        || !break3.equals(row.getString("GROUP3"))) {
                        String seriesName = this.createSeriesName(parameters, measurements, dates, break1, break2, break3);
                        sLogger.debug("Neuer Datensatz " + seriesName
                                      + "von Datens�tzen " + mStart + " / "
                                      + mEnd);
                        
                        maxGap = this.calculateMaxGap(firstRow, lastRow, mEnd-mStart);
                        
                        xyDataset.addSeries(createXYSeries(seriesName,
                                resultSet, lUpperCut, lLowerCut, mStart, mEnd,maxGap));
                        firstRow = row;
                        mStart = i;

                        break1 = row.getString("GROUP1");
                        break2 = row.getString("GROUP2"); // 3
                        break3 = row.getString("GROUP3"); // 4

                    }
                    lastRow = row;
                    mEnd = i;
                    // mEnd ++;
                    i = i + 1;
                }

                String seriesName = this.createSeriesName(parameters, measurements, dates, break1, break2, break3);
                sLogger.debug("Neuer Datensatz " + seriesName
                              + "von Datens�tzen " + mStart + " / " + mEnd);
                
                maxGap = this.calculateMaxGap(firstRow, lastRow, mEnd-mStart);
                xyDataset.addSeries(createXYSeries(seriesName, resultSet,
                        lUpperCut, lLowerCut, mStart, mEnd,maxGap));
            }else{
                xyDataset.addSeries(createXYSeries("",
                        resultSet, lUpperCut, lLowerCut, mStart, mEnd,9999));
            }
        } catch (Exception e) {
            sLogger.error(e.getMessage(), e);
        } finally {
        }
        return xyDataset;
    }
    
    
    protected double calculateMaxGap(Result firstRow, Result lastRow, int numResults){
        
        double firstValue = firstRow.getDouble("YORDINATE"); 
        // TODO Implement me. Hier ist die zentrale Frage wie wir zwischen Netzen und
        // anderen Datenquellen unterscheiden.
        return 0;
    }

    /**
     * @param parameters
     * @param measurements
     * @param break1
     * @param break2
     * @return
     */
    protected String createSeriesName(
                                    Collection<KeyValueDescibeData> break1Candidates,
                                    Collection<KeyValueDescibeData> break2Candidates,
                                    Collection<KeyValueDescibeData> break3Candidates,
                                    String break1, String break2, String break3) {
        String seriesName = findValueTitle(break1Candidates, break1)
                            + " "
                            + findValueTitle(break2Candidates,
                                    break2);
        return seriesName.trim();
    }

    private void encodeChart(JFreeChart pChart, ChartStyle pStyle,
                             OutputStream outputStream) throws IOException {
        if (sDebug)
            sLogger.debug("encodeChart()");
        KeypointPNGEncoderAdapter lEncoder = new KeypointPNGEncoderAdapter();
        lEncoder.setEncodingAlpha(true);

        int lWidth = (int) pStyle.getChartSize().getWidth();
        int lHeight = (int) pStyle.getChartSize().getHeight();

        BufferedImage lImage = pChart.createBufferedImage(lWidth, lHeight,
                Transparency.BITMASK, null);

        lEncoder.encode(lImage, outputStream);

    }

    protected String findValueTitle(Collection<KeyValueDescibeData> values,
                                  String id) {
        if (values != null) {
            Iterator<KeyValueDescibeData> it = values.iterator();
            while (it.hasNext()) {
                KeyValueDescibeData data = it.next();
                if (id.equals(data.getKey())) {
                    return data.getValue();
                }
            }
        }
        return "";
    }
}

http://dive4elements.wald.intevation.org