tim@82: /** tim@82: * 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@82: * 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@82: * created by: Stefan Blume (blume) tim@82: * erstellt am: 06.12.2007 tim@82: * Copyright: con terra GmbH, 2005 tim@82: * tim@82: * modified by: $Author: blume $ tim@82: * modified on: $Date: 2007/12/21 12:31:15 $ tim@82: * Version: $Revision: 1.8 $ tim@82: * TAG: $Name: $ tim@82: * locked from: $Locker: $ tim@82: * CVS State: $State: Exp $ tim@82: * Project: $ProjectName$ tim@82: */ tim@82: package de.intevation.gnv.chart; tim@82: tim@82: import java.awt.Color; tim@82: import java.awt.Font; tim@171: import java.awt.Transparency; tim@82: import java.awt.image.BufferedImage; tim@82: import java.io.IOException; tim@82: import java.io.OutputStream; tim@82: import java.util.Collection; tim@82: import java.util.Iterator; tim@82: tim@82: import org.apache.log4j.Logger; tim@82: import org.jfree.chart.JFreeChart; tim@82: import org.jfree.chart.axis.AxisLocation; tim@82: import org.jfree.chart.axis.NumberAxis; tim@82: import org.jfree.chart.axis.NumberTickUnit; tim@82: import org.jfree.chart.encoders.KeypointPNGEncoderAdapter; tim@82: import org.jfree.chart.plot.PlotOrientation; tim@82: import org.jfree.chart.plot.XYPlot; tim@82: import org.jfree.chart.renderer.xy.StandardXYItemRenderer; tim@82: import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; tim@82: import org.jfree.data.xy.XYDataset; tim@82: import org.jfree.data.xy.XYSeries; tim@82: import org.jfree.data.xy.XYSeriesCollection; tim@82: import org.jfree.ui.RectangleInsets; tim@82: tim@82: import de.intevation.gnv.chart.exception.TechnicalChartException; tim@82: import de.intevation.gnv.geobackend.base.Result; tim@82: import de.intevation.gnv.transition.describedata.KeyValueDescibeData; tim@82: tim@82: /** tim@82: * tim@86: * @author Tim Englich tim@171: * tim@82: */ tim@82: public class VerticalProfileChartFactory { tim@82: tim@171: /** tim@171: * Default Logging instance tim@171: */ tim@171: private static Logger sLogger = Logger tim@171: .getLogger(VerticalProfileChartFactory.class); tim@171: private static boolean sDebug = sLogger.isDebugEnabled(); tim@171: protected PlotOrientation plotOrientation = PlotOrientation.HORIZONTAL; tim@82: tim@171: public synchronized void createProfileChart( tim@171: ChartLabels pLabels, tim@171: ChartStyle pStyle, tim@171: Collection parameters, tim@171: Collection measurements, tim@179: Collection dates, tim@171: OutputStream outputStream, tim@171: Collection resultSet) tim@171: throws IOException, tim@171: TechnicalChartException { tim@171: if (sDebug) tim@171: sLogger.debug("createSimpleTimeSeriesChart()"); tim@171: int lLowerLevel = Integer.MIN_VALUE; tim@171: int lUpperLevel = Integer.MAX_VALUE; tim@171: if (pStyle.isUseUpperDataLevel() tim@171: && pStyle.getUpperLevel() < Integer.MAX_VALUE) { tim@171: lUpperLevel = pStyle.getUpperLevel(); tim@171: } tim@171: if (pStyle.isUseLowerDataLevel() tim@171: && pStyle.getLowerLevel() > Integer.MIN_VALUE) { tim@171: lLowerLevel = pStyle.getLowerLevel(); tim@171: } tim@171: if (sDebug) tim@171: sLogger.debug(" vor createDataset()"); tim@171: XYDataset lSet = this.createDataset(resultSet, lUpperLevel, tim@179: lLowerLevel, parameters, measurements, dates); tim@171: if (sDebug) tim@171: sLogger.debug(" nach createDataset()"); tim@171: final Color[] color = { Color.black, Color.red, Color.green, Color.blue }; tim@171: NumberAxis domain = new NumberAxis(pLabels.getDomainAxisLabel()); tim@82: NumberAxis axis; tim@82: StandardXYItemRenderer renderer = new StandardXYItemRenderer(); tim@171: XYPlot plot = new XYPlot(); tim@171: // Global settings tim@82: tim@171: plot.setOrientation(plotOrientation); tim@171: plot.setBackgroundPaint(Color.lightGray); tim@171: plot.setDomainGridlinePaint(Color.white); tim@171: plot.setRangeGridlinePaint(Color.white); tim@171: plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); tim@171: // plot.getRangeAxis().setFixedDimension(10.0); tim@171: plot.setDomainAxis(domain); tim@171: plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT); tim@171: if (parameters.size() == 1) { tim@171: KeyValueDescibeData parameter = parameters.iterator().next(); tim@171: axis = new NumberAxis(parameter.getValue()); tim@171: if (parameter.getValue().contains("richtung")) { tim@171: NumberAxis axis1 = new NumberAxis((parameter tim@171: .getValue()));// ,new Range(0.0,360.0)); tim@171: axis1.setTickUnit(new NumberTickUnit(30.0)); tim@171: axis1.setUpperBound(360.0); tim@171: axis1.setLowerBound(0.0); tim@171: // axis1.setDisplayRange(0.0,360.0); tim@171: plot.setRangeAxis(axis1); tim@171: } else { tim@171: axis.setFixedDimension(10.0); tim@171: axis.setAutoRangeIncludesZero(false); tim@171: plot.setRangeAxis(axis); tim@171: } tim@171: axis.configure(); tim@171: plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT); tim@171: plot.setRenderer(renderer); tim@171: plot.setDataset(lSet); tim@171: } else { tim@171: // Individual settings for different parameters tim@171: for (int i = 0; i < lSet.getSeriesCount(); i++) { tim@82: tim@171: plot.setDataset(i, getDataset((XYSeriesCollection) lSet, i)); tim@171: Color mColor = color[i % color.length]; // zyklische Farbvergabe tim@171: mColor = color[0]; tim@171: // if ( pParameterId.length==1){ tim@82: tim@171: if (((String) lSet.getSeriesKey(i)).contains("richtung")) { tim@171: NumberAxis axis1 = new NumberAxis(((String) lSet tim@171: .getSeriesKey(i)));// ,new Range(0.0,360.0)); tim@171: axis1.setTickUnit(new NumberTickUnit(30.0)); tim@171: // axis1.setDisplayRange(0.0,360.0); tim@171: axis1.setLabelPaint(mColor); tim@171: axis1.setTickLabelPaint(mColor); tim@171: axis1.setUpperBound(360.0); tim@171: axis1.setLowerBound(0.0); tim@171: plot.setRangeAxis(i, axis1); tim@82: tim@171: } else { tim@171: axis = new NumberAxis((String) lSet.getSeriesKey(i)); tim@171: axis.setFixedDimension(10.0); tim@171: axis.setAutoRangeIncludesZero(false); tim@171: axis.setLabelPaint(mColor); tim@171: axis.setTickLabelPaint(mColor); tim@171: plot.setRangeAxis(i, axis); tim@171: axis.configure(); tim@171: } tim@171: if (i % 2 != 0) tim@171: plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_RIGHT); tim@171: else tim@171: plot.setRangeAxisLocation(i, AxisLocation.BOTTOM_OR_LEFT); tim@171: plot.mapDatasetToRangeAxis(i, i); tim@171: // } tim@171: renderer = new StandardXYItemRenderer(); tim@171: renderer.setSeriesPaint(i, mColor); tim@171: // renderer.setSeriesStroke(i,stroke[j]); tim@171: plot.setRenderer(i, renderer); tim@171: } tim@171: } tim@171: JFreeChart chart = new JFreeChart(pLabels.getTitle(), new Font( tim@171: "SansSerif", Font.BOLD, 24), plot, true); tim@171: tim@171: setStyle(chart, pStyle); tim@171: configureRenderingOptions(chart); tim@171: if (sDebug) tim@171: sLogger.debug(" vor encodeChart()"); tim@171: tim@171: encodeChart(chart, pStyle, outputStream); tim@171: } tim@171: tim@171: private static XYDataset getDataset(XYSeriesCollection T, int pIndex) { // throws tim@171: // TechnicalChartException{ tim@171: // if (T.getSeriesCount() < pIndex) throw TechnicalChartException(); tim@171: XYSeriesCollection XYSC = new XYSeriesCollection(); tim@171: XYSC.addSeries(T.getSeries(pIndex)); tim@171: return XYSC; tim@171: } tim@171: tim@171: private void configureRenderingOptions(JFreeChart pJfreechart) { tim@171: org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = ((XYPlot) pJfreechart tim@171: .getPlot()).getRenderer(); tim@171: if (xyitemrenderer instanceof XYLineAndShapeRenderer) { tim@171: XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer; tim@171: xylineandshaperenderer.setBaseShapesVisible(true); tim@171: xylineandshaperenderer.setBaseShapesFilled(true); tim@171: } tim@171: } tim@171: tim@171: private void setStyle(JFreeChart pJfreechart, ChartStyle pStyle) { tim@171: if (sDebug) tim@171: sLogger.debug("setStyle()"); tim@171: pJfreechart.setBackgroundPaint(pStyle.getCanvasColor()); tim@171: XYPlot xyplot = (XYPlot) pJfreechart.getPlot(); tim@171: xyplot.setBackgroundPaint(pStyle.getPlotBackgroundColor()); tim@171: xyplot.setDomainGridlinePaint(pStyle.getDomainGridlineColor()); tim@171: xyplot.setRangeGridlinePaint(pStyle.getRangeGridlineColor()); tim@171: tim@171: Insets lOffsets = pStyle.getAxisOffset(); tim@171: RectangleInsets lRectangleInsets = new RectangleInsets(lOffsets.mUpper, tim@171: lOffsets.mLeft, lOffsets.mLower, lOffsets.mRight); tim@171: xyplot.setAxisOffset(lRectangleInsets); tim@171: xyplot.setDomainCrosshairVisible(pStyle.isDomainCrosshairVisible()); tim@171: xyplot.setRangeCrosshairVisible(pStyle.isRangeCrosshairVisible()); tim@171: tim@171: } tim@171: tim@171: protected XYSeries createXYSeries(String seriesName, tim@171: Collection resultSet, tim@171: int lUpperCut, int lLowerCut, int pStart, tim@232: int pEnd, double maxGap) throws TechnicalChartException { tim@171: if (sDebug) tim@171: sLogger.debug("createXYSeries()"); tim@171: XYSeries series = new XYSeries(seriesName); tim@171: try { tim@171: double xValue = 0; tim@171: double yValue = 0; tim@171: int i = 0; tim@171: Iterator resultIterator = resultSet.iterator(); tim@171: while (resultIterator.hasNext()) { tim@82: Result lRow = resultIterator.next(); tim@171: if (i >= pStart && i <= pEnd) { tim@171: xValue = lRow.getDouble("XORDINATE"); tim@171: yValue = lRow.getDouble("YORDINATE"); tim@171: series.add(xValue, yValue); tim@171: sLogger.debug(seriesName + " Added Value " + xValue + " / " tim@171: + yValue); tim@171: tim@171: } else if (i > pEnd) { tim@82: return series; tim@82: } tim@82: i++; tim@82: } tim@171: } catch (OutOfMemoryError e) { tim@171: sLogger.error(e.getMessage(), e); tim@171: return series; tim@82: tim@171: } catch (Exception e) { // TechnicalChartException tim@171: sLogger.error(e.getMessage(), e); tim@171: } finally { tim@171: } tim@82: tim@171: return series; tim@171: } tim@82: tim@171: private XYDataset createDataset(Collection resultSet, tim@171: int lUpperCut, int lLowerCut, tim@171: Collection parameters, tim@179: Collection measurements, tim@179: Collection dates) tim@171: throws TechnicalChartException { tim@82: tim@171: XYSeriesCollection xyDataset = new XYSeriesCollection(); tim@171: tim@171: try { tim@171: String break1, break2, break3; tim@171: int mStart = 0; tim@171: int mEnd = 0; tim@171: tim@171: Iterator resultIterator = resultSet.iterator(); tim@232: Result firstRow = null, lastRow = null; tim@232: tim@232: double maxGap; tim@171: if (resultIterator.hasNext()) { tim@171: // Row row = new Row(sArrayStrLine); tim@171: Result row = resultIterator.next(); tim@232: tim@232: firstRow = row; tim@232: lastRow = row; tim@232: tim@171: break1 = row.getString("GROUP1"); // 2 tim@171: break2 = row.getString("GROUP2"); // 3 tim@171: break3 = row.getString("GROUP3"); // 4 tim@171: int i = 1; tim@171: while (resultIterator.hasNext()) { tim@171: row = resultIterator.next(); tim@232: tim@171: if (!break1.equals(row.getString("GROUP1")) tim@171: || !break2.equals(row.getString("GROUP2")) tim@171: || !break3.equals(row.getString("GROUP3"))) { tim@179: String seriesName = this.createSeriesName(parameters, measurements, dates, break1, break2, break3); tim@171: sLogger.debug("Neuer Datensatz " + seriesName tim@171: + "von Datensätzen " + mStart + " / " tim@171: + mEnd); tim@232: tim@232: maxGap = this.calculateMaxGap(firstRow, lastRow, mEnd-mStart); tim@232: tim@171: xyDataset.addSeries(createXYSeries(seriesName, tim@232: resultSet, lUpperCut, lLowerCut, mStart, mEnd,maxGap)); tim@232: firstRow = row; tim@171: mStart = i; tim@171: tim@171: break1 = row.getString("GROUP1"); tim@171: break2 = row.getString("GROUP2"); // 3 tim@171: break3 = row.getString("GROUP3"); // 4 tim@171: tim@171: } tim@232: lastRow = row; tim@171: mEnd = i; tim@171: // mEnd ++; tim@171: i = i + 1; tim@171: } tim@171: tim@179: String seriesName = this.createSeriesName(parameters, measurements, dates, break1, break2, break3); tim@171: sLogger.debug("Neuer Datensatz " + seriesName tim@171: + "von Datensätzen " + mStart + " / " + mEnd); tim@232: tim@232: maxGap = this.calculateMaxGap(firstRow, lastRow, mEnd-mStart); tim@171: xyDataset.addSeries(createXYSeries(seriesName, resultSet, tim@232: lUpperCut, lLowerCut, mStart, mEnd,maxGap)); tim@193: }else{ tim@193: xyDataset.addSeries(createXYSeries("", tim@232: resultSet, lUpperCut, lLowerCut, mStart, mEnd,9999)); tim@171: } tim@171: } catch (Exception e) { tim@171: sLogger.error(e.getMessage(), e); tim@171: } finally { tim@171: } tim@171: return xyDataset; tim@171: } tim@232: tim@232: tim@232: protected double calculateMaxGap(Result firstRow, Result lastRow, int numResults){ tim@232: tim@232: double firstValue = firstRow.getDouble("YORDINATE"); tim@232: // TODO Implement me. Hier ist die zentrale Frage wie wir zwischen Netzen und tim@232: // anderen Datenquellen unterscheiden. tim@232: return 0; tim@232: } tim@171: tim@179: /** tim@179: * @param parameters tim@179: * @param measurements tim@179: * @param break1 tim@179: * @param break2 tim@179: * @return tim@179: */ tim@179: protected String createSeriesName( tim@179: Collection break1Candidates, tim@179: Collection break2Candidates, tim@179: Collection break3Candidates, tim@179: String break1, String break2, String break3) { tim@179: String seriesName = findValueTitle(break1Candidates, break1) tim@179: + " " tim@179: + findValueTitle(break2Candidates, tim@179: break2); tim@179: return seriesName.trim(); tim@179: } tim@179: tim@171: private void encodeChart(JFreeChart pChart, ChartStyle pStyle, tim@171: OutputStream outputStream) throws IOException { tim@171: if (sDebug) tim@171: sLogger.debug("encodeChart()"); tim@171: KeypointPNGEncoderAdapter lEncoder = new KeypointPNGEncoderAdapter(); tim@171: lEncoder.setEncodingAlpha(true); tim@171: tim@171: int lWidth = (int) pStyle.getChartSize().getWidth(); tim@171: int lHeight = (int) pStyle.getChartSize().getHeight(); tim@171: tim@171: BufferedImage lImage = pChart.createBufferedImage(lWidth, lHeight, tim@171: Transparency.BITMASK, null); tim@171: tim@171: lEncoder.encode(lImage, outputStream); tim@171: tim@171: } tim@171: tim@179: protected String findValueTitle(Collection values, tim@171: String id) { tim@171: if (values != null) { tim@110: Iterator it = values.iterator(); tim@171: while (it.hasNext()) { tim@110: KeyValueDescibeData data = it.next(); tim@171: if (id.equals(data.getKey())) { tim@171: return data.getValue(); tim@110: } tim@110: } tim@82: } tim@179: return ""; tim@82: } tim@82: }