Mercurial > dive4elements > gnv-client
view gnv-artifacts/src/main/java/de/intevation/gnv/chart/ChartFactory.java @ 327:22a6493e8460
New options in chart template: visibility of lines and points in charts and point's size.
gnv-artifacts/trunk@393 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Wed, 02 Dec 2009 10:50:12 +0000 |
parents | 219e9666f590 |
children | e964a3d8f7bc |
line wrap: on
line source
/** * Title: ChartFactory, $Header: /share/gdi/SDI-Suite/Repository/projekte/BSH-GDI/genericViewer/src/main/java/de/conterra/bsh/gdi/gnviewer/output/chart/ChartFactory.java,v 1.8 2007/12/21 12:31:15 blume Exp $ * Source: $Source: /share/gdi/SDI-Suite/Repository/projekte/BSH-GDI/genericViewer/src/main/java/de/conterra/bsh/gdi/gnviewer/output/chart/ChartFactory.java,v $ * created by: Stefan Blume (blume) * erstellt am: 06.12.2007 * Copyright: con terra GmbH, 2005 * * modified by: $Author: blume $ * modified on: $Date: 2007/12/21 12:31:15 $ * Version: $Revision: 1.8 $ * TAG: $Name: $ * locked from: $Locker: $ * CVS State: $State: Exp $ * Project: $ProjectName$ */ package de.intevation.gnv.chart; import java.awt.Color; import java.awt.Font; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import java.util.Date; import java.util.Iterator; import org.apache.log4j.Logger; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.AxisLocation; import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.NumberTickUnit; import org.jfree.chart.encoders.KeypointPNGEncoderAdapter; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.StandardXYItemRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.time.Minute; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; import org.jfree.data.xy.XYDataset; import org.jfree.ui.RectangleInsets; import de.intevation.gnv.chart.exception.TechnicalChartException; import de.intevation.gnv.geobackend.base.Result; import de.intevation.gnv.timeseries.gap.TimeGap; import de.intevation.gnv.transition.describedata.KeyValueDescibeData; /** * The class <code>ChartFactory</code> fulfills the following purposes: * <ol> * <li></li> * </ol> * * @author blume * @version 1.0 * @serial 1.0 * @see * @since 06.12.2007 17:25:59 */ public class ChartFactory { /** * Default Logging instance */ private static Logger sLogger = Logger.getLogger(ChartFactory.class); private static boolean sDebug = sLogger.isDebugEnabled(); private final static long NOTIMEGAP = Long.MAX_VALUE - 1000; // Minus 1000 damit es bei Additionen keinen �berlauf gibt public synchronized void createSimpleTimeSeriesChart( ChartLabels pLabels, ChartStyle pStyle, Collection<KeyValueDescibeData> parameters, Collection<KeyValueDescibeData> measurements, OutputStream outputStream, Collection<Result> resultSet, Collection<TimeGap> timeGaps) throws IOException, TechnicalChartException { if (sDebug) sLogger.debug("createSimpleTimeSeriesChart()"); int lLowerLevel = Integer.MIN_VALUE; int lUpperLevel = Integer.MAX_VALUE; if (pStyle.isUseUpperDataLevel() && pStyle.getUpperLevel() < Integer.MAX_VALUE) { lUpperLevel = pStyle.getUpperLevel(); } if (pStyle.isUseLowerDataLevel() && pStyle.getLowerLevel() > Integer.MIN_VALUE) { lLowerLevel = pStyle.getLowerLevel(); } if (sDebug) sLogger.debug(" vor createDataset()"); XYDataset lSet = this.createDataset(resultSet, lUpperLevel, lLowerLevel, parameters, measurements,timeGaps); if (sDebug) sLogger.debug(" nach createDataset()"); final Color[] color = { Color.black, Color.red, Color.green, Color.blue }; DateAxis domain = new DateAxis(pLabels.getDomainAxisLabel()); NumberAxis axis; StandardXYItemRenderer renderer = new StandardXYItemRenderer(); XYPlot plot = new XYPlot(); // Global settings plot.setOrientation(PlotOrientation.VERTICAL); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); // plot.getRangeAxis().setFixedDimension(10.0); plot.setDomainAxis(domain); plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT); if (parameters.size() == 1) { KeyValueDescibeData parameter = parameters.iterator().next(); axis = new NumberAxis(parameter.getValue()); if (parameter.getValue().contains("richtung")) { NumberAxis axis1 = new NumberAxis((parameter .getValue()));// ,new Range(0.0,360.0)); axis1.setTickUnit(new NumberTickUnit(30.0)); axis1.setUpperBound(360.0); axis1.setLowerBound(0.0); // axis1.setDisplayRange(0.0,360.0); plot.setRangeAxis(axis1); } else { axis.setFixedDimension(10.0); axis.setAutoRangeIncludesZero(false); plot.setRangeAxis(axis); } axis.configure(); plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT); plot.setRenderer(renderer); plot.setDataset(lSet); } else { // Individual settings for different parameters for (int i = 0; i < lSet.getSeriesCount(); i++) { plot.setDataset(i, getDataset((TimeSeriesCollection) lSet, i)); Color mColor = color[i % color.length]; // zyklische Farbvergabe mColor = color[0]; // if ( pParameterId.length==1){ if (((String) lSet.getSeriesKey(i)).contains("richtung")) { NumberAxis axis1 = new NumberAxis(((String) lSet .getSeriesKey(i)));// ,new Range(0.0,360.0)); axis1.setTickUnit(new NumberTickUnit(30.0)); // axis1.setDisplayRange(0.0,360.0); axis1.setLabelPaint(mColor); axis1.setTickLabelPaint(mColor); axis1.setUpperBound(360.0); axis1.setLowerBound(0.0); plot.setRangeAxis(i, axis1); } else { axis = new NumberAxis((String) lSet.getSeriesKey(i)); axis.setFixedDimension(10.0); axis.setAutoRangeIncludesZero(false); axis.setLabelPaint(mColor); axis.setTickLabelPaint(mColor); plot.setRangeAxis(i, axis); axis.configure(); } if (i % 2 != 0) plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_RIGHT); else plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_LEFT); plot.mapDatasetToRangeAxis(i, i); // } renderer = new StandardXYItemRenderer(); renderer.setSeriesPaint(i, mColor); // renderer.setSeriesStroke(i,stroke[j]); plot.setRenderer(i, renderer); } } JFreeChart chart = new JFreeChart(pLabels.getTitle(), new Font( "SansSerif", Font.BOLD, 24), plot, true); setStyle(chart, pStyle); configureRenderingOptions(chart); if (sDebug) sLogger.debug(" vor encodeChart()"); encodeChart(chart, pStyle, outputStream); } private static XYDataset getDataset(TimeSeriesCollection T, int pIndex) { // throws // TechnicalChartException{ // if (T.getSeriesCount() < pIndex) throw TechnicalChartException(); TimeSeriesCollection TSC = new TimeSeriesCollection(); TSC.addSeries(T.getSeries(pIndex)); return TSC; } private void configureRenderingOptions(JFreeChart pJfreechart) { org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = ((XYPlot) pJfreechart .getPlot()).getRenderer(); if (xyitemrenderer instanceof XYLineAndShapeRenderer) { XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer; xylineandshaperenderer.setBaseShapesVisible(true); xylineandshaperenderer.setBaseShapesFilled(true); } } private void setStyle(JFreeChart pJfreechart, ChartStyle pStyle) { if (sDebug) sLogger.debug("setStyle()"); pJfreechart.setBackgroundPaint(pStyle.getCanvasColor()); XYPlot xyplot = (XYPlot) pJfreechart.getPlot(); xyplot.setBackgroundPaint(pStyle.getPlotBackgroundColor()); xyplot.setDomainGridlinePaint(pStyle.getDomainGridlineColor()); xyplot.setRangeGridlinePaint(pStyle.getRangeGridlineColor()); Insets lOffsets = pStyle.getAxisOffset(); RectangleInsets lRectangleInsets = new RectangleInsets(lOffsets.mUpper, lOffsets.mLeft, lOffsets.mLower, lOffsets.mRight); xyplot.setAxisOffset(lRectangleInsets); xyplot.setDomainCrosshairVisible(pStyle.isDomainCrosshairVisible()); xyplot.setRangeCrosshairVisible(pStyle.isRangeCrosshairVisible()); } private TimeSeries createTimeSeries(String pTimeSeriesName, Collection<Result> resultSet, int lUpperCut, int lLowerCut, int pStart, int pEnd, long maxGap) throws TechnicalChartException { if (sDebug) sLogger.debug("createTimeSeries()"); Result lRow0, lRow1; Date lDate = null, lDate0 = null; TimeSeries lTimeseries = new TimeSeries(pTimeSeriesName, org.jfree.data.time.Minute.class); try { long lDateDiff = 0; double lValue = 0; int i = 0; Iterator<Result> resultIterator = resultSet.iterator(); while (resultIterator.hasNext()) { Result lRow = resultIterator.next(); if (i >= pStart + 1 && i <= pEnd) { if (i == pStart + 1) { lRow0 = lRow;// lDate = lRow0.getDate("XORDINATE"); lDate0 = lDate; lValue = lRow0.getDouble("YORDINATE"); if (lValue > lLowerCut && lValue < lUpperCut) { // lTimeseries.addOrUpdate(new Minute(lDate), // lValue); lTimeseries.add(new Minute(lDate), lValue); } } // for (int i = pStart+1; i <= pEnd; i++) { lRow1 = lRow; lDate = lRow1.getDate("XORDINATE"); lValue = lRow1.getDouble("YORDINATE"); lDateDiff = lDate.getTime() - lDate0.getTime(); if (lDateDiff > maxGap) { // add 1 minute in millisecs to left hand side Date // and insert Dummy to break line lDate0.setTime((lDate0.getTime() + 60000)); lTimeseries.addOrUpdate(new Minute(lDate0), null); lTimeseries.addOrUpdate(new Minute(lDate), lValue); // lTimeseries.add(new Minute(lDate0), null); } else if (lDateDiff == 0) { if (sDebug) sLogger.debug("Datediff: " + lDateDiff + " bei index : " + i + " Datum : " + lDate + " " + lDate0); } else if (lValue > lLowerCut && lValue < lUpperCut) { lTimeseries.addOrUpdate(new Minute(lDate), lValue); // lTimeseries.add(new Minute(lDate), lValue); } lRow0 = lRow1; lDate0 = lDate; } else if (i > pEnd) { return lTimeseries; } i++; } } catch (OutOfMemoryError e) { sLogger.error(e.getMessage(), e); return lTimeseries; } catch (Exception e) { // TechnicalChartException sLogger.error(e.getMessage(), e); } finally { } return lTimeseries; } private XYDataset createDataset(Collection<Result> resultSet, int lUpperCut, int lLowerCut, Collection<KeyValueDescibeData> parameters, Collection<KeyValueDescibeData> measurements, Collection<TimeGap> timeGaps) throws TechnicalChartException { TimeSeriesCollection lTimeSeriesCollection = new TimeSeriesCollection(); try { Date dStart = null, dEnd = null; String break1, break2, break3; int mStart = 0; int mEnd = 0; Iterator<Result> resultIterator = resultSet.iterator(); if (resultIterator.hasNext()) { Result row = resultIterator.next(); break1 = row.getString("GROUP1"); // 2 break2 = row.getString("GROUP2"); // 3 break3 = row.getString("GROUP3"); // 4 dStart = row.getDate("XORDINATE"); int i = 1; Integer gapID = -1; while (resultIterator.hasNext()) { row = resultIterator.next(); if (!break1.equals(row.getString("GROUP1")) || !break2.equals(row.getString("GROUP2")) || !break3.equals(row.getString("GROUP3"))) { String mTimeSeriesName = findValueTitle(parameters, break1) + " " + findValueTitle(measurements, break2) + "m"; long maxGap = this.calculateMaxGap(dStart, dEnd,mStart, mEnd, gapID.intValue(), timeGaps); lTimeSeriesCollection.addSeries(createTimeSeries( mTimeSeriesName, resultSet, lUpperCut, lLowerCut, mStart, mEnd,maxGap)); mStart = i; dStart = row.getDate("XORDINATE"); break1 = row.getString("GROUP1"); break2 = row.getString("GROUP2"); // 3 break3 = row.getString("GROUP3"); // 4 } mEnd = i; dEnd = row.getDate("XORDINATE"); gapID = row.getInteger("GAPID"); i = i + 1; } String mTimeSeriesName = findValueTitle(parameters, break1) + " " + findValueTitle(measurements, break2) + "m"; long maxGap = this.calculateMaxGap(dStart, dEnd,mStart, mEnd,gapID.intValue(), timeGaps); lTimeSeriesCollection.addSeries(createTimeSeries( mTimeSeriesName, resultSet, lUpperCut, lLowerCut, mStart, mEnd, maxGap)); }else{ // Es sind keine Daten vorhanden: Es wird eine Zeitserie eingef�gt. lTimeSeriesCollection.addSeries(createTimeSeries( "", resultSet, lUpperCut, lLowerCut, mStart, mEnd, 999999)); } } catch (Exception e) { sLogger.error(e.getMessage(), e); } finally { } return lTimeSeriesCollection; } /** * @param dStart * @param dEnd */ private long calculateMaxGap(Date dStart, Date dEnd, int pStart , int pEnd, int gapID, Collection<TimeGap> timeGaps) { // umgesetzt nach issue 45 // Handle Gaps > 0.5% timeserieslength, // i.e do not draw here long maxGap = (dEnd.getTime() - dStart.getTime()) / 200; // 0,5 prozent der L�nge long timeInterval = this.getTimeGapValue(dStart, dEnd, pStart, pEnd, gapID, timeGaps); if (maxGap < timeInterval){ maxGap = timeInterval + 10; } // if (maxGap < (dEnd.getTime() - dStart.getTime()) // / (pEnd - pStart)) // maxGap = (dEnd.getTime() - dStart.getTime()) // / (pEnd - pStart) + 1000; return maxGap; } private long getTimeGapValue(Date dStart, Date dEnd, int pStart ,int pEnd, int gapID, Collection<TimeGap> timeGaps){ long gap = 0; if (gapID < 0 || gapID >= 99){ if (gapID == -1){ // Mesh gap = NOTIMEGAP; // Es gibt keine L�cken in Netzen. }else if (pEnd-pStart < 60){ gap = (3/(pEnd-pStart)) * (dEnd.getTime() - dStart.getTime()); } }else{ Iterator<TimeGap> it = timeGaps.iterator(); while (it.hasNext()){ TimeGap tempTimeGap = it.next(); if (tempTimeGap.getKey() == gapID){ int gapValue = tempTimeGap.getValue(); String unit = tempTimeGap.getUnit(); 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)){ // TODO wie soll das laufen gap = gapValue * (TimeGap.DAY_IN_MILLIS *30); }else if (unit.equals(TimeGap.TIME_UNIT_YEAR)){ // TODO wie soll das laufen f�r schaltjahre gap = gapValue * (TimeGap.DAY_IN_MILLIS *365); } break; } } } return gap; } private void encodeChart(JFreeChart pChart, ChartStyle pStyle, OutputStream outputStream) throws IOException { if (sDebug) sLogger.debug("encodeChart()"); KeypointPNGEncoderAdapter lEncoder = new KeypointPNGEncoderAdapter(); lEncoder.setEncodingAlpha(true); int lWidth = (int) pStyle.getChartSize().getWidth(); int lHeight = (int) pStyle.getChartSize().getHeight(); BufferedImage lImage = pChart.createBufferedImage(lWidth, lHeight, Transparency.BITMASK, null); lEncoder.encode(lImage, outputStream); } private String findValueTitle(Collection<KeyValueDescibeData> values, String pMmtId) { int id = 0; try { id = Integer.parseInt(pMmtId); } catch (NumberFormatException e) { sLogger.warn(e, e); return pMmtId; } Iterator<KeyValueDescibeData> it = values.iterator(); while (it.hasNext()) { KeyValueDescibeData data = it.next(); if (id == Integer.parseInt(data.getKey())) { return data.getValue(); } } return ""; } }