tim@65: /** tim@65: * 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 $ tim@65: * Source: $Source: /share/gdi/SDI-Suite/Repository/projekte/BSH-GDI/genericViewer/src/main/java/de/conterra/bsh/gdi/gnviewer/output/chart/ChartFactory.java,v $ tim@65: * created by: Stefan Blume (blume) tim@65: * erstellt am: 06.12.2007 tim@65: * Copyright: con terra GmbH, 2005 tim@65: * tim@65: * modified by: $Author: blume $ tim@65: * modified on: $Date: 2007/12/21 12:31:15 $ tim@65: * Version: $Revision: 1.8 $ tim@65: * TAG: $Name: $ tim@65: * locked from: $Locker: $ tim@65: * CVS State: $State: Exp $ tim@65: * Project: $ProjectName$ tim@65: */ tim@65: package de.intevation.gnv.chart; tim@65: tim@65: import java.awt.Color; tim@65: import java.awt.Font; tim@65: import java.awt.image.BufferedImage; tim@65: import java.io.IOException; tim@67: import java.io.OutputStream; tim@67: import java.util.Collection; tim@65: import java.util.Date; tim@67: import java.util.Iterator; tim@65: tim@65: import org.apache.log4j.Logger; tim@65: import org.jfree.chart.JFreeChart; tim@65: import org.jfree.chart.axis.AxisLocation; tim@65: import org.jfree.chart.axis.DateAxis; tim@65: import org.jfree.chart.axis.NumberAxis; tim@65: import org.jfree.chart.axis.NumberTickUnit; tim@65: import org.jfree.chart.encoders.KeypointPNGEncoderAdapter; tim@65: import org.jfree.chart.plot.PlotOrientation; tim@65: import org.jfree.chart.plot.XYPlot; tim@65: import org.jfree.chart.renderer.xy.StandardXYItemRenderer; tim@65: import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; tim@65: import org.jfree.data.time.Minute; tim@65: import org.jfree.data.time.TimeSeries; tim@65: import org.jfree.data.time.TimeSeriesCollection; tim@65: import org.jfree.data.xy.XYDataset; tim@65: import org.jfree.ui.RectangleInsets; tim@65: tim@67: import de.intevation.gnv.chart.exception.TechnicalChartException; tim@67: import de.intevation.gnv.geobackend.base.Result; tim@67: import de.intevation.gnv.transition.describedata.KeyValueDescibeData; tim@65: tim@65: /** tim@65: * The class ChartFactory fulfills the following purposes: tim@65: *
    tim@65: *
  1. tim@65: *
tim@65: * tim@65: * @author blume tim@65: * @version 1.0 tim@65: * @serial 1.0 tim@65: * @see tim@65: * @since 06.12.2007 17:25:59 tim@65: */ tim@65: public class ChartFactory { tim@65: tim@65: /** tim@65: * Default Logging instance tim@65: */ tim@65: private static Logger sLogger = Logger.getLogger(ChartFactory.class); tim@65: private static boolean sDebug = sLogger.isDebugEnabled(); tim@65: tim@65: tim@86: public synchronized void createSimpleTimeSeriesChart(ChartLabels pLabels, ChartStyle pStyle, Collection parameters, Collection measurements, OutputStream outputStream, Collection resultSet) throws IOException, TechnicalChartException { tim@65: if (sDebug) tim@65: sLogger.debug("createSimpleTimeSeriesChart()"); tim@65: int lLowerLevel = Integer.MIN_VALUE; tim@65: int lUpperLevel = Integer.MAX_VALUE; tim@65: if (pStyle.isUseUpperDataLevel() tim@65: && pStyle.getUpperLevel() < Integer.MAX_VALUE) { tim@65: lUpperLevel = pStyle.getUpperLevel(); tim@65: } tim@65: if (pStyle.isUseLowerDataLevel() tim@65: && pStyle.getLowerLevel() > Integer.MIN_VALUE) { tim@65: lLowerLevel = pStyle.getLowerLevel(); tim@65: } tim@65: if (sDebug) tim@65: sLogger.debug(" vor createDataset()"); tim@86: XYDataset lSet = this.createDataset(resultSet, lUpperLevel, tim@68: lLowerLevel,parameters,measurements); tim@65: if (sDebug) tim@65: sLogger.debug(" nach createDataset()"); tim@65: final Color[] color = {Color.black, Color.red, Color.green, Color.blue}; tim@86: DateAxis domain = new DateAxis(pLabels.getDomainAxisLabel()); tim@65: NumberAxis axis; tim@65: StandardXYItemRenderer renderer = new StandardXYItemRenderer(); tim@65: XYPlot plot = new XYPlot(); tim@65: //Global settings tim@65: tim@65: plot.setOrientation(PlotOrientation.VERTICAL); tim@65: plot.setBackgroundPaint(Color.lightGray); tim@65: plot.setDomainGridlinePaint(Color.white); tim@65: plot.setRangeGridlinePaint(Color.white); tim@65: plot.setAxisOffset(new RectangleInsets(5.0,5.0,5.0,5.0)); tim@65: //plot.getRangeAxis().setFixedDimension(10.0); tim@65: plot.setDomainAxis(domain); tim@65: plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT); tim@68: if (parameters.size() == 1) { tim@68: KeyValueDescibeData parameter = parameters.iterator().next(); tim@68: axis = new NumberAxis(parameter.getValue()); tim@68: if(parameter.getValue().contains("richtung")){ tim@65: NumberAxis axis1 = new NumberAxis( tim@68: ((String) parameter.getValue()));//,new Range(0.0,360.0)); tim@65: axis1.setTickUnit(new NumberTickUnit(30.0)); tim@65: axis1.setUpperBound(360.0); tim@65: axis1.setLowerBound(0.0); tim@65: //axis1.setDisplayRange(0.0,360.0); tim@65: plot.setRangeAxis( axis1); tim@65: }else{ tim@65: axis.setFixedDimension(10.0); tim@65: axis.setAutoRangeIncludesZero(false); tim@65: plot.setRangeAxis(axis); tim@65: } tim@65: axis.configure(); tim@65: plot.setRangeAxisLocation( AxisLocation.BOTTOM_OR_LEFT); tim@65: plot.setRenderer(renderer); tim@65: plot.setDataset(lSet); tim@65: } else { tim@65: // Individual settings for different parameters tim@65: for (int i = 0; i < lSet.getSeriesCount(); i++) { tim@65: tim@65: plot.setDataset(i, getDataset((TimeSeriesCollection) lSet, i)); tim@65: Color mColor=color[i % color.length]; // zyklische Farbvergabe tim@65: mColor = color[0]; tim@65: // if ( pParameterId.length==1){ tim@65: tim@65: if(((String) lSet.getSeriesKey(i)).contains("richtung")){ tim@65: NumberAxis axis1 = new NumberAxis(((String) lSet.getSeriesKey(i)));//,new Range(0.0,360.0)); tim@65: axis1.setTickUnit(new NumberTickUnit(30.0)); tim@65: //axis1.setDisplayRange(0.0,360.0); tim@65: axis1.setLabelPaint(mColor); tim@65: axis1.setTickLabelPaint(mColor); tim@65: axis1.setUpperBound(360.0); tim@65: axis1.setLowerBound(0.0); tim@65: plot.setRangeAxis(i, axis1); tim@65: tim@65: tim@65: } tim@65: else { tim@65: axis = new NumberAxis((String) lSet.getSeriesKey(i)); tim@65: axis.setFixedDimension(10.0); tim@65: axis.setAutoRangeIncludesZero(false); tim@65: axis.setLabelPaint(mColor); tim@65: axis.setTickLabelPaint(mColor); tim@65: plot.setRangeAxis(i, axis); tim@65: axis.configure(); tim@65: } tim@65: if (i % 2 != 0) tim@65: plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_RIGHT); tim@65: else tim@65: plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_LEFT); tim@65: plot.mapDatasetToRangeAxis(i, i); tim@65: // } tim@65: renderer = new StandardXYItemRenderer(); tim@65: renderer.setSeriesPaint(i, mColor); tim@65: // renderer.setSeriesStroke(i,stroke[j]); tim@65: plot.setRenderer(i, renderer); tim@65: } tim@65: } tim@65: JFreeChart chart = new JFreeChart( tim@65: pLabels.getTitle(), tim@65: new Font ("SansSerif",Font.BOLD,24), tim@65: plot,true); tim@65: tim@65: tim@65: setStyle(chart, pStyle); tim@65: configureRenderingOptions(chart); tim@65: if (sDebug) tim@65: sLogger.debug(" vor encodeChart()"); tim@65: tim@67: encodeChart(chart, pStyle, outputStream); tim@65: } tim@67: private static XYDataset getDataset(TimeSeriesCollection T, int pIndex){ //throws TechnicalChartException{ tim@67: //if (T.getSeriesCount() < pIndex) throw TechnicalChartException(); tim@65: TimeSeriesCollection TSC = new TimeSeriesCollection(); tim@65: TSC.addSeries(T.getSeries(pIndex)); tim@65: return (XYDataset) TSC; tim@65: } tim@67: tim@65: private void configureRenderingOptions(JFreeChart pJfreechart) { tim@65: org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = ((XYPlot) pJfreechart tim@65: .getPlot()).getRenderer(); tim@65: if (xyitemrenderer instanceof XYLineAndShapeRenderer) { tim@65: XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer; tim@65: xylineandshaperenderer.setBaseShapesVisible(true); tim@65: xylineandshaperenderer.setBaseShapesFilled(true); tim@65: } tim@65: } tim@65: tim@65: private void setStyle(JFreeChart pJfreechart, ChartStyle pStyle) { tim@65: if (sDebug) tim@65: sLogger.debug("setStyle()"); tim@65: pJfreechart.setBackgroundPaint(pStyle.getCanvasColor()); tim@65: XYPlot xyplot = (XYPlot) pJfreechart.getPlot(); tim@65: xyplot.setBackgroundPaint(pStyle.getPlotBackgroundColor()); tim@65: xyplot.setDomainGridlinePaint(pStyle.getDomainGridlineColor()); tim@65: xyplot.setRangeGridlinePaint(pStyle.getRangeGridlineColor()); tim@65: tim@65: Insets lOffsets = pStyle.getAxisOffset(); tim@65: RectangleInsets lRectangleInsets = new RectangleInsets(lOffsets.mUpper, tim@65: lOffsets.mLeft, lOffsets.mLower, lOffsets.mRight); tim@65: xyplot.setAxisOffset(lRectangleInsets); tim@65: xyplot.setDomainCrosshairVisible(pStyle.isDomainCrosshairVisible()); tim@65: xyplot.setRangeCrosshairVisible(pStyle.isRangeCrosshairVisible()); tim@65: tim@65: } tim@65: tim@65: tim@67: private TimeSeries createTimeSeries(String pTimeSeriesName, Collection resultSet, tim@67: int lUpperCut, int lLowerCut,int pStart,int pEnd, Date dStart, Date dEnd) throws TechnicalChartException{ tim@65: if (sDebug) tim@65: sLogger.debug("createTimeSeries()"); tim@100: Result lRow0, lRow1; tim@65: tim@65: Date lDate=null, lDate0=null; tim@65: tim@67: TimeSeries lTimeseries = new TimeSeries(pTimeSeriesName, tim@65: org.jfree.data.time.Minute.class); tim@65: try { tim@65: long maxGap=0, lDateDiff=0; tim@65: double lValue=0; tim@67: tim@65: tim@65: int i = 0; tim@67: Iterator resultIterator = resultSet.iterator(); tim@67: while (resultIterator.hasNext()){ tim@67: Result lRow = resultIterator.next(); tim@65: if (i >= pStart+1 && i <= pEnd){ tim@65: if (i == pStart+1){ tim@67: lRow0 = lRow;// tim@65: tim@65: // Handle Gaps > 0.5% timeserieslength, i.e do not draw here tim@65: // +TODO mache maxGap variabel über diagram options tim@65: maxGap = (dEnd.getTime() - dStart.getTime()) / 200; // 0,5 prozent der Länge tim@65: if (maxGap < 3600000) maxGap=3600010; tim@65: if (maxGap <(dEnd.getTime() - dStart.getTime())/(pEnd-pStart)) tim@65: maxGap = (dEnd.getTime() - dStart.getTime())/(pEnd-pStart) + 1000; tim@65: tim@65: if (sDebug) tim@65: sLogger.debug("MaxGap : "+maxGap/1000+" Länge : "+(dEnd.getTime() - dStart.getTime())/1000+ tim@65: "Intervall "+(dEnd.getTime() - dStart.getTime())/(pEnd-pStart)/1000); tim@82: lDate = lRow0.getDate("XORDINATE"); tim@65: lDate0 = lDate; tim@82: lValue = lRow0.getDouble("YORDINATE"); tim@65: if (lValue > lLowerCut && lValue < lUpperCut){ tim@65: //lTimeseries.addOrUpdate(new Minute(lDate), lValue); tim@65: lTimeseries.add(new Minute(lDate), lValue); tim@65: } tim@65: } tim@65: //for (int i = pStart+1; i <= pEnd; i++) { tim@67: lRow1 =lRow; tim@82: lDate = lRow1.getDate("XORDINATE"); tim@82: lValue = lRow1.getDouble("YORDINATE"); tim@65: lDateDiff = lDate.getTime() - lDate0.getTime(); tim@65: if (lDateDiff > maxGap) { tim@65: // add 1 minute in millisecs to left hand side Date tim@65: // and insert Dummy to break line tim@65: lDate0.setTime((lDate0.getTime() + 60000)); tim@65: lTimeseries.addOrUpdate(new Minute(lDate0), null); tim@65: lTimeseries.addOrUpdate(new Minute(lDate), lValue); tim@65: //lTimeseries.add(new Minute(lDate0), null); tim@65: } else if (lDateDiff == 0) { tim@65: if (sDebug) tim@65: sLogger.debug("Datediff: "+lDateDiff+" bei index : "+i+" Datum : "+lDate+" "+lDate0); tim@65: } tim@65: else if (lValue > lLowerCut && lValue < lUpperCut) { tim@65: lTimeseries.addOrUpdate(new Minute(lDate), lValue); tim@65: //lTimeseries.add(new Minute(lDate), lValue); tim@65: } tim@65: lRow0 = lRow1; tim@65: lDate0 = lDate; tim@100: }else if (i > pEnd){ tim@100: return lTimeseries; tim@65: } tim@65: i++; tim@65: } tim@65: tim@65: tim@65: } catch (OutOfMemoryError e) { tim@65: sLogger.error(e.getMessage(), e); tim@65: return lTimeseries; tim@65: tim@67: } catch (Exception e) { //TechnicalChartException tim@65: sLogger.error(e.getMessage(), e); tim@65: } tim@65: finally { tim@65: } tim@65: tim@65: return lTimeseries; tim@65: } tim@65: tim@86: private XYDataset createDataset(Collection resultSet, tim@68: int lUpperCut, int lLowerCut,Collection parameters, Collection measurements) throws TechnicalChartException { tim@65: tim@65: TimeSeriesCollection lTimeSeriesCollection = new TimeSeriesCollection(); tim@65: try{ tim@65: Date dStart = null, dEnd= null; tim@82: String break1, break2, break3; tim@65: int mStart = 0; tim@65: int mEnd = 0; tim@65: tim@65: tim@67: Iterator resultIterator = resultSet.iterator(); tim@67: if (resultIterator.hasNext()){ tim@67: Result row = resultIterator.next(); tim@67: tim@82: break1 = row.getString("GROUP1"); // 2 tim@82: break2 = row.getString("GROUP2"); //3 tim@82: break3 = row.getString("GROUP3"); // 4 tim@82: dStart = row.getDate("XORDINATE"); tim@67: int i = 1; tim@67: while (resultIterator.hasNext()) { tim@67: row = resultIterator.next(); tim@82: if (!break1.equals(row.getString("GROUP1")) tim@82: || !break2 .equals(row.getString("GROUP2")) tim@82: || !break3.equals(row.getString("GROUP3"))){ tim@68: String mTimeSeriesName = findValueTitle(parameters,break1)+" "+ tim@68: findValueTitle(measurements,break2)+"m"; tim@67: tim@67: lTimeSeriesCollection.addSeries(createTimeSeries(mTimeSeriesName, tim@67: resultSet, lUpperCut, lLowerCut, mStart, mEnd, dStart, dEnd)); tim@67: mStart = i; tim@82: dStart = row.getDate("XORDINATE"); tim@82: break1 = row.getString("GROUP1"); tim@82: break2 = row.getString("GROUP2"); //3 tim@82: break3 = row.getString("GROUP3"); // 4 tim@67: tim@67: } tim@67: mEnd = i; tim@82: dEnd = row.getDate("XORDINATE"); tim@67: i = i + 1; tim@67: } tim@65: tim@68: String mTimeSeriesName = findValueTitle(parameters,break1)+" "+ tim@68: findValueTitle(measurements,break2)+"m"; tim@65: lTimeSeriesCollection.addSeries(createTimeSeries(mTimeSeriesName, tim@67: resultSet, lUpperCut, lLowerCut, mStart, mEnd, dStart, dEnd)); tim@67: } tim@65: } tim@65: catch (Exception e){ tim@65: sLogger.error(e.getMessage(), e); tim@65: } tim@65: finally{ tim@65: } tim@65: return lTimeSeriesCollection; tim@65: } tim@65: tim@65: tim@65: tim@67: private void encodeChart(JFreeChart pChart, ChartStyle pStyle, OutputStream outputStream) tim@65: throws IOException { tim@65: if (sDebug) tim@65: sLogger.debug("encodeChart()"); tim@65: KeypointPNGEncoderAdapter lEncoder = new KeypointPNGEncoderAdapter(); tim@65: lEncoder.setEncodingAlpha(true); tim@65: tim@65: int lWidth = (int) pStyle.getChartSize().getWidth(); tim@65: int lHeight = (int) pStyle.getChartSize().getHeight(); tim@65: tim@65: BufferedImage lImage = pChart.createBufferedImage(lWidth, lHeight, tim@65: BufferedImage.BITMASK, null); tim@67: tim@67: lEncoder.encode(lImage, outputStream); tim@67: tim@67: } tim@65: tim@82: private String findValueTitle(Collection values, String pMmtId){ tim@82: int id = 0; tim@82: try { tim@82: id = Integer.parseInt(pMmtId); tim@82: } catch (NumberFormatException e) { tim@82: sLogger.warn(e,e); tim@82: return pMmtId; tim@82: } tim@82: tim@82: Iterator it = values.iterator(); tim@68: while(it.hasNext()){ tim@68: KeyValueDescibeData data = it.next(); tim@86: if (id ==Integer.parseInt(data.getKey())){ tim@68: return data.getValue(); tim@68: } tim@65: } tim@65: return ""; tim@65: } tim@65: }