Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/exports/InfoGeneratorHelper.java @ 4410:c9e06ba9359a
ExtremeWQCurveGenerator: Fixed typo in debug output.
author | Felix Wolfsteller <felix.wolfsteller@intevation.de> |
---|---|
date | Mon, 05 Nov 2012 17:30:23 +0100 |
parents | 4ac581062c40 |
children | e8a4d2fd25cc |
line wrap: on
line source
package de.intevation.flys.exports; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Rectangle2D; import java.util.Date; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.apache.log4j.Logger; import org.jfree.chart.ChartRenderingInfo; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.XYPlot; import org.jfree.data.Range; import org.jfree.data.xy.XYDataset; import de.intevation.artifacts.common.ArtifactNamespaceContext; import de.intevation.artifacts.common.utils.XMLUtils; import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; import de.intevation.flys.jfree.Bounds; /** * This class helps generating chart info documents. * * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public class InfoGeneratorHelper { private static final Logger logger = Logger.getLogger(InfoGeneratorHelper.class); protected ChartGenerator generator; public InfoGeneratorHelper(ChartGenerator generator) { this.generator = generator; } /** * Triggers the creation of the chart info document. * * @param chart The JFreeChart chart. * @param info An info object that has been created while chart creation. * * @return the info document. */ public Document createInfoDocument( JFreeChart chart, ChartRenderingInfo info) { logger.debug("InfoGeneratorHelper.createInfoDocument"); Document doc = XMLUtils.newDocument(); ElementCreator cr = new ElementCreator( doc, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX); Element chartinfo = cr.create("chartinfo"); chartinfo.appendChild(createAxesElements(cr, chart)); chartinfo.appendChild(createTransformationElements(cr, chart, info)); doc.appendChild(chartinfo); return doc; } /** * This method create a axes element that contains all domain and range * axes of the given chart. * * @param cr The ElementCreator. * @param chart The chart that provides range information of its axes. * * @return an element with axes information. */ protected Element createAxesElements( ElementCreator cr, JFreeChart chart) { logger.debug("InfoGeneratorHelper.createRangeElements"); Element axes = cr.create("axes"); XYPlot plot = (XYPlot) chart.getPlot(); int dAxisCount = plot.getDomainAxisCount(); for (int i = 0; i < dAxisCount; i++) { ValueAxis axis = plot.getDomainAxis(i); XYDataset data = plot.getDataset(i); if (axis != null) { Element e = createAxisElement(cr, axis, data, "domain", i); axes.appendChild(e); } } int rAxisCount = plot.getRangeAxisCount(); for (int i = 0; i < rAxisCount; i++) { ValueAxis axis = plot.getRangeAxis(i); XYDataset data = plot.getDataset(i); if (axis == null || data == null) { logger.warn("Axis or dataset is empty at pos: " + i); continue; } Element e = createAxisElement(cr, axis, data, "range", i); axes.appendChild(e); } return axes; } /** * This method create a axis element for a given <i>axis</i> and * <i>type</i>. Type can be one of 'domain' or 'range'. * * @param cr The ElementCreator * @param axis The axis that provides range information. * @param dataset The dataset for min/max determination. * @param type The axis type ('domain' or 'range'). * @param pos The position in the chart. * * @return An element that contains range information of a given axis. */ protected Element createAxisElement( ElementCreator cr, ValueAxis axis, XYDataset dataset, String type, int pos) { logger.debug("createAxisElement " + pos); logger.debug("Axis is from type: " + axis.getClass()); Element e = cr.create(type); cr.addAttr(e, "pos", String.valueOf(pos), true); if (axis instanceof DateAxis) { prepareDateAxisElement( e, cr, (DateAxis) axis, dataset, type, pos); } else { prepareNumberAxisElement( e, cr, (NumberAxis) axis, dataset, type, pos); } return e; } protected Element prepareNumberAxisElement( Element e, ElementCreator cr, NumberAxis axis, XYDataset dataset, String type, int pos ) { Range range = axis.getRange(); cr.addAttr(e, "from", String.valueOf(range.getLowerBound()), true); cr.addAttr(e, "to", String.valueOf(range.getUpperBound()), true); cr.addAttr(e, "axistype", "number", true); Range[] rs = generator.getRangesForAxis(pos); Range r = null; if (type.equals("range")) { r = rs[1]; } else { r = rs[0]; } cr.addAttr(e, "min", String.valueOf(r.getLowerBound()), true); cr.addAttr(e, "max", String.valueOf(r.getUpperBound()), true); return e; } protected Element prepareDateAxisElement( Element e, ElementCreator cr, DateAxis axis, XYDataset dataset, String type, int pos ) { Date from = axis.getMinimumDate(); Date to = axis.getMaximumDate(); Bounds bounds = null; if (type.equals("range")) { bounds = generator.getYBounds(pos); } else { bounds = generator.getXBounds(pos); } cr.addAttr(e, "axistype", "date", true); cr.addAttr(e, "from", String.valueOf(from.getTime()), true); cr.addAttr(e, "to", String.valueOf(to.getTime()), true); cr.addAttr(e, "min", bounds.getLower().toString(), true); cr.addAttr(e, "max", bounds.getUpper().toString(), true); return e; } /** * This method appends the values of a transformation matrix to transform * image pixel coordinates into chart coordinates. * * @param cr The ElementCreator. * @param chart The chart object. * @param info The ChartRenderingInfo that is filled while chart creation. * * @return an element that contains one or more transformation matrix. */ protected Element createTransformationElements( ElementCreator cr, JFreeChart chart, ChartRenderingInfo info) { logger.debug("InfoGeneratorHelper.createTransformationElements"); Element tf = cr.create("transformation-matrix"); Rectangle2D dataArea = info.getPlotInfo().getDataArea(); XYPlot plot = (XYPlot) chart.getPlot(); ValueAxis xAxis = plot.getDomainAxis(); if (xAxis == null) { logger.error("There is no x axis in the chart!"); return null; } for (int i = 0, num = plot.getRangeAxisCount(); i < num; i++) { ValueAxis yAxis = plot.getRangeAxis(i); if (yAxis == null) { logger.warn("No y axis at pos " + i + " existing."); continue; } Element matrix = createTransformationElement( cr, xAxis, yAxis, dataArea, i); tf.appendChild(matrix); } return tf; } /** * Creates an element that contains values used to transform coordinates * of a coordinate system A into a coordinate system B. * * @param cr The ElementCreator. * @param xAxis The x axis of the target coordinate system. * @param yAxis The y axis of the target coordinate system. * @param dataArea The pixel coordinates of the chart image. * @param pos The dataset position. * * @return an element that contains transformation matrix values. */ protected Element createTransformationElement( ElementCreator cr, ValueAxis xAxis, ValueAxis yAxis, Rectangle2D dataArea, int pos) { double[] tm = createTransformationMatrix(dataArea, xAxis, yAxis); Element matrix = cr.create("matrix"); cr.addAttr(matrix, "pos", String.valueOf(pos), true); cr.addAttr(matrix, "sx", String.valueOf(tm[0]), true); cr.addAttr(matrix, "sy", String.valueOf(tm[1]), true); cr.addAttr(matrix, "tx", String.valueOf(tm[2]), true); cr.addAttr(matrix, "ty", String.valueOf(tm[3]), true); if (xAxis instanceof DateAxis) { cr.addAttr(matrix, "xtype", "date", true); } else { cr.addAttr(matrix, "xtype", "number", true); } if (yAxis instanceof DateAxis) { cr.addAttr(matrix, "ytype", "date", true); } else { cr.addAttr(matrix, "ytype", "number", true); } return matrix; } /** * This method determines a transformation matrix to transform pixel * coordinates of the chart image into chart coordinates. * * @param dataArea The rectangle that contains the data points of the chart. * @param xAxis The x axis. * @param yAxis The y axis. * * @return a double array as follows: [sx, sy, tx, ty]. */ protected static double[] createTransformationMatrix( Rectangle2D dataArea, ValueAxis xAxis, ValueAxis yAxis) { logger.debug("InfoGeneratorHelper.createTransformationMatrix"); double offsetX = dataArea.getX(); double width = dataArea.getWidth(); double offsetY = dataArea.getY(); double height = dataArea.getHeight(); Range xRange = getRangeFromAxis(xAxis); Range yRange = getRangeFromAxis(yAxis); double lowerX = xRange.getLowerBound(); double upperX = xRange.getUpperBound(); double lowerY = yRange.getLowerBound(); double upperY = yRange.getUpperBound(); if (xAxis.isInverted()) { logger.info("X-Axis is inverted!"); double tmp = upperX; upperX = lowerX; lowerX = tmp; } double dMoveX = upperX - lowerX; double fMoveX = width * lowerX; double dMoveY = lowerY - upperY; double fMoveY = height * upperY; AffineTransform t1 = AffineTransform.getTranslateInstance( offsetX - ( fMoveX / dMoveX ), offsetY - ( fMoveY / dMoveY ) ); AffineTransform t2 = AffineTransform.getScaleInstance( width / (upperX - lowerX), height / (lowerY - upperY)); t1.concatenate(t2); try { t1.invert(); double[] c = new double[6]; t1.getMatrix(c); return new double[] { c[0], c[3], c[4], c[5] }; } catch (NoninvertibleTransformException e) { // do nothing logger.warn("Matrix is not invertible."); } return new double[] { 1d, 1d, 0d, 0d }; } protected static Range getRangeFromAxis(ValueAxis axis) { if (axis instanceof DateAxis) { DateAxis dAxis = (DateAxis) axis; Date min = dAxis.getMinimumDate(); Date max = dAxis.getMaximumDate(); return new Range(min.getTime(), max.getTime()); } else { return axis.getRange(); } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :