view gnv-artifacts/src/main/java/de/intevation/gnv/chart/VerticalProfileChart.java @ 522:c896282c2601

Issue 156 solved. Added width, height and points as parameter to svg and pdf output mode. Width and height have an effact on the width and height of the export, points is a boolean property which enables/disables the drawing of data points. gnv-artifacts/trunk@616 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Mon, 25 Jan 2010 09:18:31 +0000
parents 04a242c67fe6
children d2c68f2f619b
line wrap: on
line source
package de.intevation.gnv.chart;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;

import org.apache.log4j.Logger;

import org.jfree.chart.ChartTheme;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.general.Series;
import org.jfree.data.xy.XYSeriesCollection;

import de.intevation.gnv.geobackend.base.Result;
import de.intevation.gnv.state.describedata.KeyValueDescibeData;


/**
 * @author Ingo Weinzierl <ingo.weinzierl@intevation.de>
 */
public class VerticalProfileChart
extends      AbstractXYLineChart
{
    private static Logger log = Logger.getLogger(VerticalProfileChart.class);

    protected final double PERCENTAGE     = 5.0;
    protected final double GAP_MAX_LEVEL  = Math.sqrt(2.0);
    protected final int    GAP_MAX_VALUES = 60;


    public VerticalProfileChart(
        ChartLabels labels,
        ChartTheme  theme,
        Collection  parameters,
        Collection  measurements,
        Collection  dates,
        Collection  result,
        Collection  timeGaps,
        Locale      locale,
        boolean     linesVisible,
        boolean     shapesVisible
    ) {
        this.labels           = labels;
        this.theme            = theme;
        this.parameters       = parameters;
        this.measurements     = measurements;
        this.dates            = dates;
        this.resultSet        = result;
        this.timeGaps         = timeGaps;
        this.locale           = locale;
        this.PLOT_ORIENTATION = PlotOrientation.HORIZONTAL;
        this.linesVisible     = linesVisible;
        this.shapesVisible    = shapesVisible;
        this.datasets         = new HashMap();
        this.ranges           = new HashMap();
    }


    protected void initData() {
        log.debug("init data for VerticalProfileChart");

        String  breakPoint1       = null;
        String  breakPoint2       = null;
        String  breakPoint3       = null;

        Iterator iter       = resultSet.iterator();
        Result   row        = null;
        String   seriesName = null;
        String   parameter  = null;
        XYSeries series     = null;

        int idx           = 0;
        int startPos      = 0;
        int endPos        = 0;
        double startValue = 0;
        double endValue   = 0;

        Result[] results =
            (Result[]) resultSet.toArray(new Result[resultSet.size()]);

        while (iter.hasNext()) {
            row = (Result) iter.next();

            // add current data to plot and prepare for next one
            if (!row.getString("GROUP1").equals(breakPoint1) ||
                !row.getString("GROUP2").equals(breakPoint2) ||
                !row.getString("GROUP3").equals(breakPoint3)
            ) {
                log.debug("prepare data/plot for next dataset");

                if(series != null) {
                    gapDetection(results, series, startPos, endPos);
                    addSeries(series, parameter, idx);

                    startPos = endPos +1;
                }

                // prepare variables for next plot
                breakPoint1 = row.getString("GROUP1");
                breakPoint2 = row.getString("GROUP2");
                breakPoint3 = row.getString("GROUP3");

                seriesName  = createSeriesName(
                    breakPoint1,
                    breakPoint2,
                    breakPoint3
                );
                parameter = findParameter(seriesName);

                log.debug("next dataset is '" + seriesName + "'");
                series = new XYSeries(seriesName);
            }

            addValue(row, series);
            Double value = row.getDouble("YORDINATE");
            if (value != null)
                storeMaxRange(value, parameter);
            endPos++;
        }

        if (results.length == 0)
            return;

        gapDetection(results, series, startPos, endPos);
        addSeries(series, parameter, idx);

        addDatasets();
    }


    protected void gapDetection(
        Result[] results,
        Series   series,
        int      startPos,
        int      endPos
    ) {
        double startValue = results[startPos].getDouble("XORDINATE");
        double endValue   = results[endPos-1].getDouble("XORDINATE");
        if (results[0].getInteger("DATAID") == 2)
            addGapsOnGrid(results, series, startPos, endPos);
        else
            addGaps(results, series, startValue, endValue, startPos, endPos);
    }


    protected void addValue(Result row, Series series) {
        ((XYSeries) series).add(
            row.getDouble("XORDINATE"),
            row.getDouble("YORDINATE")
        );
    }


    protected void addSeries(Series series, String parameter, int idx) {
        log.debug("add series (" + parameter + ")to chart");

        if (series == null) {
            log.warn("no data to add");
            return;
        }

        XYSeriesCollection xysc = null;

        if (datasets.containsKey(parameter))
            xysc = (XYSeriesCollection) datasets.get(parameter);
        else
            xysc = new XYSeriesCollection();

        xysc.addSeries((XYSeries) series);
        datasets.put(parameter, xysc);
    }


    protected void addDatasets() {
        Iterator   iter = parameters.iterator();
        XYPlot     plot = chart.getXYPlot();
        int        idx  = 0;

        XYSeriesCollection   xysc = null;
        KeyValueDescibeData  data = null;
        String               key  = null;
        while (iter.hasNext()) {
            data = (KeyValueDescibeData) iter.next();
            key  = data.getValue();

            if (datasets.containsKey(key)) {
                xysc  = (XYSeriesCollection)datasets.get(key);
                plot.setDataset(idx, xysc );
                log.debug("Added " + key + " parameter to plot.");
                prepareAxis(key, idx);
                adjustRenderer(
                    idx++,
                    xysc.getSeriesCount(),
                    linesVisible,
                    shapesVisible
                );
            }
        }
    }


    protected void localizeDomainAxis(Axis axis, Locale locale) {
        // call localizeRangeAxis from superclass which formats NumberAxis
        super.localizeRangeAxis(axis, locale);
    }


    protected String createSeriesName(
        String breakPoint1,
        String breakPoint2,
        String breakPoint3
    ) {
        log.debug("create seriesname of verticalprofile chart");
        return findValueTitle(parameters, breakPoint1) +
            " " +
            findValueTitle(measurements, breakPoint2) +
            "m";
    }


    protected void addGapsOnGrid(
        Result[] results,
        Series   series,
        int      startPos,
        int      endPos
    ) {
        String axis = getDependendAxisName(
            results[startPos],
            results[startPos+1]
        );
        double range        = 0;
        int    last         = 0;
        int    current      = 0;

        for (int i = startPos+1; i < endPos; i++) {
            last    = results[i-1].getInteger(axis);
            current = results[i].getInteger(axis);

            boolean detected = gridDetection(last, current);

            if (detected) {
                double xOld = results[i-1].getDouble("XORDINATE");
                double xNow = results[i].getDouble("XORDINATE");
                log.debug("Gap detected on grid between "+ xOld +" and "+ xNow);
                ((XYSeries) series).add(xOld+0.0001, null);
            }
        }
    }


    protected void addGaps(
        Result[] results,
        Series   series,
        double   startValue,
        double   endValue,
        int      startPos,
        int      endPos
    ) {

        double last    = 0;
        double current = 0;
        int    num     = results.length;

        for (int i = startPos+1; i < endPos; i++) {
            boolean detected = false;

            last    = results[i-1].getDouble("YORDINATE");
            current = results[i].getDouble("YORDINATE");

            // gap detection for more than GAP_MAX_VALUES values
            if (num > GAP_MAX_VALUES)
                detected = simpleDetection(startValue, endValue, last, current);
            // gap detection for less than GAP_MAX_VALUES values
            else
                detected = specialDetection(
                    startValue,
                    endValue,
                    last,
                    current,
                    num
                );

            if (detected) {
                log.info("Gap between " + last + " and " + current);
                ((XYSeries) series).add((last+current)/2, null);
            }
        }
    }


    protected boolean simpleDetection(
        double start,
        double end,
        double last,
        double current
    ) {
        double delta      = Math.abs(end - start);
        double smallDelta = Math.abs(current - last);

        return (smallDelta > delta / 100 * PERCENTAGE);
    }


    protected boolean specialDetection(
        double start,
        double end,
        double last,
        double current,
        int    count
    ) {
        double delta      = Math.abs(end - start);
        double smallDelta = Math.abs(current - last);

        return (smallDelta > (3.0 / (count - 1) * delta));
    }

    
    protected boolean gridDetection(double last, double current) {
        return (Math.abs(current - last) > GAP_MAX_LEVEL);
    }


    protected String getDependendAxisName(Result first, Result second) {
        return "KPOSITION";
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org