changeset 329:42a5269636eb

Added time gap detection to time series charts. gnv-artifacts/trunk@395 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 02 Dec 2009 15:42:46 +0000
parents 861d939e587c
children 477c0c46605e
files gnv-artifacts/ChangeLog gnv-artifacts/src/main/java/de/intevation/gnv/chart/TimeSeriesChart.java
diffstat 2 files changed, 137 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/gnv-artifacts/ChangeLog	Wed Dec 02 11:07:40 2009 +0000
+++ b/gnv-artifacts/ChangeLog	Wed Dec 02 15:42:46 2009 +0000
@@ -1,3 +1,9 @@
+2009-12-02  Ingo Weinzierl <ingo.weinzierl@intevation.de>
+
+	* src/main/java/de/intevation/gnv/chart/TimeSeriesChart.java: Added time gap
+	  detection. If a time gap is detected, a null value will be inserted to 
+	  break the current line.
+
 2009-12-02  Ingo Weinzierl <ingo.weinzierl@intevation.de>
 
 	* pom.xml: Added JBoss repository for JFreeChart 1.0.13 and removed explicit 
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/chart/TimeSeriesChart.java	Wed Dec 02 11:07:40 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/chart/TimeSeriesChart.java	Wed Dec 02 15:42:46 2009 +0000
@@ -3,6 +3,7 @@
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.Locale;
 
@@ -21,6 +22,7 @@
 import org.jfree.data.time.TimeSeriesCollection;
 
 import de.intevation.gnv.geobackend.base.Result;
+import de.intevation.gnv.timeseries.gap.TimeGap;
 
 
 /**
@@ -32,6 +34,8 @@
 
     private static final String DATE_FORMAT = "dd-MMM";
 
+    private static final long   NO_TIME_GAP = Long.MAX_VALUE - 1000;
+
     private static Logger log = Logger.getLogger(TimeSeriesChart.class);
 
 
@@ -96,7 +100,14 @@
         String     seriesName = null;
         TimeSeries series     = null;
 
-        int idx = 0;
+        int  idx       = 0;
+        int  startPos  = 0;
+        int  endPos    = 0;
+        Date startDate = null;
+        Date endDate   = null;
+
+        Result[] results =
+            (Result[]) resultSet.toArray(new Result[resultSet.size()]);
 
         while (iter.hasNext()) {
             row = (Result) iter.next();
@@ -109,9 +120,15 @@
                 log.debug("prepare data/plot for next dataset");
 
                 if(series != null) {
+                    // add gaps before adding series to chart
+                    startDate = results[startPos].getDate("XORDINATE");
+                    endDate   = results[endPos-1].getDate("XORDINATE");
+                    addGaps(results,series,startDate,endDate,startPos,endPos);
                     addSeries(series, idx);
+
                     prepareAxis(((String)series.getKey()), idx);
                     adjustRenderer(idx++, linesVisible, shapesVisible);
+                    startPos  = endPos + 1;
                 }
 
                 // prepare variables for next plot
@@ -127,12 +144,19 @@
 
                 log.debug("next dataset is '" + seriesName + "'");
                 series = new TimeSeries(seriesName, Minute.class);
+
+                // set values of start date and start position in collection for
+                // next parameter
             }
 
             addValue(row, series);
+            endPos++;
         }
 
         // add the last dataset if existing to plot and prepare its axis
+        startDate = results[startPos].getDate("XORDINATE");
+        endDate = results[endPos-1].getDate("XORDINATE");
+        addGaps(results, series, startDate, endDate, startPos, endPos);
         addSeries(series, idx);
 
         if (series != null) {
@@ -143,7 +167,6 @@
 
 
     protected void addValue(Result row, Series series) {
-        // TODO look for gaps between two values
         ((TimeSeries) series).addOrUpdate(
             new Minute(row.getDate("XORDINATE")),
             row.getDouble("YORDINATE")
@@ -190,5 +213,111 @@
             findValueTitle(measurements, breakPoint2) +
             "m";
     }
+
+
+    protected void addGaps(
+        Result[] results,
+        Series   series,
+        Date     startDate,
+        Date     endDate,
+        int      startPos,
+        int      endPos
+    ) {
+        int  gapID   = results[startPos].getInteger("GAPID");
+        long maxDiff = calculateGapSize(
+            startDate, endDate, startPos, endPos, gapID
+        );
+
+        Date last = startDate;
+        for (int i = startPos+1; i < endPos; i++) {
+            Result res = results[i];
+            Date   now = res.getDate("XORDINATE");
+
+            if ((now.getTime() - last.getTime()) > maxDiff) {
+                // add gap, add 1 minute to last date and add null value
+                log.info(
+                    "Gap between " +
+                    last.toString() + " and " + now.toString()
+                );
+                last.setTime(last.getTime() + 60000);
+                ((TimeSeries) series).addOrUpdate(new Minute(last), null);
+            }
+
+            last = now;
+        }
+    }
+
+
+    protected long calculateGapSize(
+        Date start,
+        Date end,
+        int  startPos,
+        int  endPos,
+        int  gapID
+    ){
+        long maxGap   = (end.getTime() - start.getTime()) / 20;
+        long interval = getTimeGapValue(start, end, startPos, endPos, gapID);
+
+        if (maxGap < interval)
+            maxGap = interval + 10;
+
+        return maxGap;
+    }
+
+
+    protected long getTimeGapValue(
+        Date dStart,
+        Date dEnd,
+        int  pStart,
+        int  pEnd,
+        int  gapID
+    ){
+        long gap = 0;
+
+        if (gapID < 0 || gapID >= 99) {
+
+            if (gapID == -1) {
+                // no gaps in meshes
+                gap = NO_TIME_GAP;
+            }
+            else if (pEnd-pStart < 60) {
+                gap = (3/(pEnd-pStart)) * (dEnd.getTime() - dStart.getTime());
+            }
+        }
+        else{
+            Iterator it = timeGaps.iterator();
+
+            while (it.hasNext()) {
+                TimeGap tempTimeGap = (TimeGap) it.next();
+
+                if (tempTimeGap.getKey() == gapID){
+                    String unit     = tempTimeGap.getUnit();
+                    int    gapValue = tempTimeGap.getValue();
+
+                    if (unit.equals(TimeGap.TIME_UNIT_MINUTE)) {
+                        gap = gapValue * TimeGap.MINUTE_IN_MILLIS;
+                    }
+                    else if (unit.equals(TimeGap.TIME_UNIT_HOUR)) {
+                        gap = gapValue * TimeGap.HOUR_IN_MILLIS;
+                    }
+                    else if (unit.equals(TimeGap.TIME_UNIT_DAY)) {
+                        gap = gapValue * TimeGap.DAY_IN_MILLIS;
+                    }
+                    else if (unit.equals(TimeGap.TIME_UNIT_WEEK)) {
+                        gap = gapValue * TimeGap.WEEK_IN_MILLIS;
+                    }
+                    else if (unit.equals(TimeGap.TIME_UNIT_MONTH)) {
+                        gap = gapValue * (TimeGap.DAY_IN_MILLIS *30);
+                    }
+                    else if (unit.equals(TimeGap.TIME_UNIT_YEAR)) {
+                        gap = gapValue * (TimeGap.DAY_IN_MILLIS *365);
+                    }
+                    break;
+                }
+            }
+        }
+
+        return gap;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org