view gnv-artifacts/src/main/java/de/intevation/gnv/chart/VerticalProfileChart.java @ 605:e8ebdbc7f1e3

First step of removing the cache blob. The static part of the describe document will be created by using the input data stored at each state. Some TODOs left (see ChangeLog). gnv-artifacts/trunk@671 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Tue, 09 Feb 2010 14:27:55 +0000
parents d2c68f2f619b
children 24a85678bd39
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
{
    public static final String DEFAULT_AXIS = "KPOSITION";

    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 = null;
        
        if (results.length > (startPos+1)) {
            axis = getDependendAxisName(
                results[startPos],
                results[startPos+1]
            );
        }
        else {
            axis = DEFAULT_AXIS;
        }

        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