view gnv-artifacts/src/main/java/de/intevation/gnv/chart/HorizontalProfileChart.java @ 364:2413273f1c13

Workarround: Store lower and upper bounds of data while iterating over all data and set the max range of axes with these information. JFreeCharts method NumberAxis.setAutoRange(true) doesn't seem to work properly. gnv-artifacts/trunk@439 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 16 Dec 2009 11:58:44 +0000
parents 07a64cfafdf1
children 061355435075
line wrap: on
line source
package de.intevation.gnv.chart;

import java.util.Collection;
import java.util.Locale;

import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.WKTReader;
import com.vividsolutions.jts.io.ParseException;

import org.apache.log4j.Logger;

import org.jfree.chart.ChartTheme;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.general.Series;
import org.jfree.data.xy.XYSeries;

import de.intevation.gnv.geobackend.base.Result;
import de.intevation.gnv.utils.DistanceCalculator;


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

    private static WKTReader wktReader = new WKTReader();
    private        Point     lastPoint;
    private        double    distance;


    public HorizontalProfileChart(
        ChartLabels labels,
        ChartTheme  theme,
        Collection  parameters,
        Collection  measurements,
        Collection  dates,
        Collection  result,
        Collection  timeGaps,
        Locale      locale,
        boolean     linesVisible,
        boolean     shapesVisible
    ) {
        super(
            labels,
            theme,
            parameters,
            measurements,
            dates,
            result,
            timeGaps,
            locale,
            linesVisible,
            shapesVisible
        );
        this.PLOT_ORIENTATION = PlotOrientation.VERTICAL;
        this.distance         = 0;
    }


    protected void gapDetection(
        Result[] results,
        Series   series,
        int      startPos,
        int      endPos
    ) {
        log.debug("Start gap detection.");
        try {
            Point startValue = getPoint(results[startPos]);
            Point endValue   = getPoint(results[endPos-1]);
            if (results[0].getInteger("DATAID") == 2)
                addGapsOnGrid(results, series, startPos, endPos);
            else
                addGaps(
                    results,
                    series,
                    startValue,
                    endValue,
                    startPos,
                    endPos
                );
        }
        catch (ParseException pe) {
            log.warn(
                "Error while parsing points for gap detection. " +
                "No gaps for current series will be detected."
            );
        }

        log.debug("Gap detection finished.");
    }


    protected void addValue(Result row, Series series) {
        try {
            Point point = (Point) wktReader.read(row.getString("SHAPE"));
            if (lastPoint != null)
                distance = distance + DistanceCalculator.calculateDistance(
                    lastPoint, point
                );
            lastPoint = point;

            ((XYSeries) series).add(
                distance,
                row.getDouble("YORDINATE")
            );
        }
        catch(ParseException pe) {
            log.warn("No data found while parsing.");
        }
    }


    protected void addSeries(Series series, String label, int idx) {
        super.addSeries(series, label, idx);

        // reset values used by current series for next series
        lastPoint = null;
        distance  = 0;
    }


    protected String createSeriesName(
        String breakPoint1,
        String breakPoint2,
        String breakPoint3
    ) {
        log.debug("create seriesname of horizontalprofile chart");
        return super.createSeriesName(
            breakPoint1,
            breakPoint2,
            breakPoint3) +
            " " +
            findValueTitle(dates, breakPoint3);
    }


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

        double range        = 0;
        double distance     = 0;
        int    last         = 0;
        int    current      = 0;
        Point  lastPoint    = null;
        Point  currentPoint = null;

        for (int i = startPos+1; i < endPos; i++) {
            try {
                last         = results[i-1].getInteger(axis);
                lastPoint    = getPoint(results[i-1]);
                current      = results[i].getInteger(axis);
                currentPoint = getPoint(results[i]);
                distance     = DistanceCalculator.calculateDistance(
                    lastPoint,
                    currentPoint
                );

                boolean detected = gridDetection(last, current);

                if (detected) {
                    log.debug(
                        "Gap detected on grid between " + range +
                        " and " + (range+distance)
                    );

                    ((XYSeries) series).add(range+0.0001, null);
                }

                range += distance;
            }
            catch (ParseException pe) {
                log.warn("Error while parsing point for gap detection.", pe);
            }
        }
    }


    protected void addGaps(
        Result[] results,
        Series   series,
        Point    startValue,
        Point    endValue,
        int      startPos,
        int      endPos
    ) {
        double range = 0;
        Point  last  = null;
        Point  now   = null;

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

            try {
                last   = (Point) getPoint(results[i-1]);
                now    = (Point) getPoint(results[i]);

                // gap detection for more than GAP_MAX_VALUES values
                if (results.length > GAP_MAX_VALUES)
                    detected = simpleDetection(startValue, endValue, last, now);
                // gap detection for less than GAP_MAX_VALUES values
                else
                    detected = specialDetection(
                        startValue,
                        endValue,
                        last,
                        now,
                        results.length
                    );

                // gap detected, insert null value to break line
                if (detected) {
                    log.info("Gap after " + range);
                    double x = range + 0.0001;

                    ((XYSeries)series).add(x, null);
                }

                range += DistanceCalculator.calculateDistance(last,now);
            }
            catch (ParseException pe) {
                log.warn("Error while parsing point.");
            }

        }
    }


    protected boolean simpleDetection(
        Point start,
        Point end,
        Point last,
        Point current
    ) {
        double delta      = DistanceCalculator.calculateDistance(start, end);
        double deltaSmall = DistanceCalculator.calculateDistance(last,current);

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


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

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


    private Point getPoint(Result result)
    throws ParseException
    {
        return (Point) wktReader.read(result.getString("SHAPE"));
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org