# HG changeset patch # User Raimund Renkert # Date 1409821837 -7200 # Node ID 209f8a9e8a750e0b7ce66e116293927aac0d58af # Parent bb770daccd1d6e2e02fbe536cebcac0575fd3452 Added new processor to plot misc discharge data, e.g. from datacage or recommendations. diff -r bb770daccd1d -r 209f8a9e8a75 artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Mon Sep 01 10:15:57 2014 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Thu Sep 04 11:10:37 2014 +0200 @@ -17,6 +17,7 @@ import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.model.WQKms; import org.dive4elements.river.exports.process.DischargeProcessor; +import org.dive4elements.river.exports.process.MiscDischargeProcessor; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StickyAxisAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; @@ -113,7 +114,7 @@ return; } - DischargeProcessor dProcessor = new DischargeProcessor(getRange()[0]); + MiscDischargeProcessor dProcessor = new MiscDischargeProcessor(getRange()[0]); if (dProcessor.canHandle(name)) { dProcessor.doOut(this, artifactFacet, attr, visible, YAXIS.W.idx); } diff -r bb770daccd1d -r 209f8a9e8a75 artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java Mon Sep 01 10:15:57 2014 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java Thu Sep 04 11:10:37 2014 +0200 @@ -16,6 +16,7 @@ import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.WQKms; import org.dive4elements.river.exports.process.DischargeProcessor; +import org.dive4elements.river.exports.process.MiscDischargeProcessor; import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; import org.dive4elements.river.jfree.Bounds; import org.dive4elements.river.jfree.DoubleBounds; @@ -260,7 +261,7 @@ String name = artifactFacet.getFacetName(); logger.debug("DischargeCurveGenerator.doOut: " + name); - DischargeProcessor dProcessor = new DischargeProcessor(getRange()[0]); + MiscDischargeProcessor dProcessor = new MiscDischargeProcessor(getRange()[0]); if (dProcessor.canHandle(name)) { // In Base DischargeCurveGenerator, always at gauge, use WCm axis. dProcessor.doOut(this, artifactFacet, theme, visible, YAXIS.WCm.idx); diff -r bb770daccd1d -r 209f8a9e8a75 artifacts/src/main/java/org/dive4elements/river/exports/process/MiscDischargeProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/MiscDischargeProcessor.java Thu Sep 04 11:10:37 2014 +0200 @@ -0,0 +1,316 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.exports.process; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.exports.DiagramGenerator; +import org.dive4elements.river.exports.DischargeCurveGenerator; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.RiverAnnotation; +import org.dive4elements.river.jfree.StickyAxisAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; + +import org.jfree.chart.annotations.XYTextAnnotation; + + +/** Helper for data handling in discharge diagrams. */ +public class MiscDischargeProcessor +extends DefaultProcessor implements FacetTypes { + + private final static Logger logger = + Logger.getLogger(MiscDischargeProcessor.class); + + /** Station for which the diagram is shown. */ + private double km; + + /** Tolerance for comparison of kilometers. */ + public static final double KM_EPSILON = 0.001d; + + + /** This processor needs to be constructed with a given km. */ + public MiscDischargeProcessor() { + km = Double.NaN; + } + + + public MiscDischargeProcessor(double km) { + this.km = km; + } + + public void doOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible) { + CallContext context = generator.getCallContext(); + Object data = bundle.getData(context); + if (data instanceof WQKms) { + doWQKmsPointOut( + generator, (WQKms) data, bundle, theme, visible); + return; + } + else if (data instanceof RiverAnnotation) { + doRiverAnnotationOut( + generator, (RiverAnnotation)data, bundle, theme, visible); + return; + } + else if (data instanceof double[][]) { + doPointsOut(generator, (double[][])data, bundle, theme, visible); + } + else { + logger.error("Can't process " + + data.getClass().getName() + " objects of facet " + + bundle.getFacetName()); + } + } + + /** Process data, add it to plot. */ + @Override + public void doOut( + XYChartGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible, + int axisIndex + ) { + CallContext context = generator.getCallContext(); + Object data = bundle.getData(context); + /* TODO: Remove the first case.*/ + if (bundle.getFacetName().equals(STATIC_WQ)) { + doPointOut( + generator, bundle, theme, visible, axisIndex); + } + else if (data instanceof WQKms) { + doWQKmsPointOut( + generator, (WQKms) data, bundle, theme, visible, axisIndex); + return; + } + else if (data instanceof RiverAnnotation) { + doRiverAnnotationOut( + generator, (RiverAnnotation) data, bundle, theme, visible); + return; + } + else if (data instanceof double[][]) { + doMarksOut( + generator, (double[][]) data, bundle, theme, visible); + return; + } + else { + logger.error("Can't process " + + data.getClass().getName() + " objects of facet " + + bundle.getFacetName()); + } + } + + private void doPointOut(XYChartGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible, + int axisIndex + ) { + XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme); + Object wq = bundle.getData(generator.getCallContext()); + if (wq instanceof double[][]) { + double [][] data = (double [][]) wq; + StyledSeriesBuilder.addPoints(series, data, true); + } else if (wq instanceof WQKms) { + WQKms wqkms = (WQKms) wq; + StyledSeriesBuilder.addPointsQW(series, (WQKms) wq); + } + + generator.addAxisSeries(series, axisIndex, visible); + } + + /** Handle WQKms data by finding w/q values at given km. */ + protected void doWQKmsPointOut(XYChartGenerator generator, + WQKms wqkms, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible, + int axidx + ) { + logger.debug("doWQKmsPointOut"); + String title = bundle.getFacetDescription(); + XYSeries series = new StyledXYSeries( + title, + theme); + + double[] kms = wqkms.getKms(); + + for (int i = 0 ; i< kms.length; i++) { + if (Math.abs(kms[i] - getKm()) <= KM_EPSILON) { + series.add(wqkms.getQ(i), wqkms.getW(i)); + generator.addAxisSeries(series, axidx, visible); + if(visible && theme.parseShowPointLabel()) { + List textAnnos = new ArrayList(); + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + title, + wqkms.getQ(i), + // TODO add a percentage to the extend of W axis + wqkms.getW(i)); + textAnnos.add(anno); + RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + generator.addAnnotations(flysAnno); + } + return; + } + } + + logger.warn("No WQ found for km " + getKm()); + } + + protected void doRiverAnnotationOut(XYChartGenerator generator, + RiverAnnotation annotations, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + if (!(generator instanceof DischargeCurveGenerator)) { + logger.error("DischargeProcessor can only be used in " + + " in DischargeCurveGenerator-classes."); + return; + } + logger.debug("doRiverAnnotationOut"); + DischargeCurveGenerator dGenerator = + (DischargeCurveGenerator) generator; + + dGenerator.translateRiverAnnotation(annotations); + dGenerator.doAnnotations( + annotations, + bundle, theme, visible); + } + + + /** + * Put Sticky Axis Markers to Y-axis for each value. + * @param data [[-,y1],[-,y2],...] ('x'-coordinates ignored) + */ + protected void doMarksOut(XYChartGenerator generator, + double[][] data, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + logger.debug("doMarksOut"); + + if (!visible) { + return; + } + + // TODO subtract gauge null point if at gauge. + String title = bundle.getFacetDescription(); + List yMarks = new ArrayList(); + + for (double yPos: data[1]) { + yMarks.add(new StickyAxisAnnotation( + title, + (float) yPos, + StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + } + + generator.doAnnotations(new RiverAnnotation(title, yMarks), + bundle, theme, visible); + } + + /** True if this processor knows how to deal with facetType. */ + @Override + public boolean canHandle(String facetType) { + return STATIC_WQKMS_W.equals(facetType) + || COMPUTED_DISCHARGE_MAINVALUES_Q.equals(facetType) + || MAINVALUES_Q.equals(facetType) + || COMPUTED_DISCHARGE_MAINVALUES_W.equals(facetType) + || MAINVALUES_W.equals(facetType) + || STATIC_W_INTERPOL.equals(facetType) + || STATIC_WQ.equals(facetType) + || STATIC_WQ_ANNOTATIONS.equals(facetType); + } + + + /** The station of the current calculation/view. */ + protected double getKm() { + return km; + } + + private void doPointsOut( + DiagramGenerator generator, + double[][] data, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data, true); + generator.addAxisSeries(series, axisName, visible); + } + + /** Handle WQKms data by finding w/q values at given km. */ + protected void doWQKmsPointOut( + DiagramGenerator generator, + WQKms wqkms, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + logger.debug("doWQKmsPointOut"); + String title = bundle.getFacetDescription(); + XYSeries series = new StyledXYSeries( + title, + theme); + + double[] kms = wqkms.getKms(); + + for (int i = 0 ; i< kms.length; i++) { + if (Math.abs(kms[i] - getKm()) <= KM_EPSILON) { + series.add(wqkms.getQ(i), wqkms.getW(i)); + generator.addAxisSeries(series, axisName, visible); + if(visible && theme.parseShowPointLabel()) { + List textAnnos = new ArrayList(); + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + title, + wqkms.getQ(i), + // TODO add a percentage to the extend of W axis + wqkms.getW(i)); + textAnnos.add(anno); + RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + generator.addAnnotations(flysAnno); + } + return; + } + } + + logger.warn("No WQ found for km " + getKm()); + } + + protected void doRiverAnnotationOut(DiagramGenerator generator, + RiverAnnotation annotations, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + if (visible) { + annotations.setTheme(theme); + generator.addAnnotations(annotations); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :