view gnv-artifacts/src/main/java/de/intevation/gnv/chart/HorizontalProfileChart.java @ 469:62fc63d0f71d

Added a new State in Product Verticalprofile in Timeseriespoints. Now it will be displayed the Years where measurements happened and than only the dates of the chosen Year will be fetched and displayed. gnv-artifacts/trunk@532 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Tue, 12 Jan 2010 12:42:53 +0000
parents 061355435075
children 24a85678bd39
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));
    }

    @Override
    protected String getDependendAxisName(Result first, Result second) {
        if (first.getInteger("IPOSITION") == second.getInteger("IPOSITION"))
            return "JPOSITION";

        return "IPOSITION";
    }

    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