rrenkert@8181: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde rrenkert@8181: * Software engineering by Intevation GmbH rrenkert@8181: * rrenkert@8181: * This file is Free Software under the GNU AGPL (>=v3) rrenkert@8181: * and comes with ABSOLUTELY NO WARRANTY! Check out the rrenkert@8181: * documentation coming with Dive4Elements River for details. rrenkert@8181: */ rrenkert@8181: rrenkert@8181: package org.dive4elements.river.exports.process; rrenkert@8181: rrenkert@8181: import java.util.ArrayList; rrenkert@8181: import java.util.List; rrenkert@8181: rrenkert@8181: import org.apache.log4j.Logger; rrenkert@8181: import org.jfree.data.xy.XYSeries; rrenkert@8181: rrenkert@8181: import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; rrenkert@8181: import org.dive4elements.artifacts.CallContext; rrenkert@8181: import org.dive4elements.river.artifacts.model.FacetTypes; rrenkert@8181: import org.dive4elements.river.artifacts.model.WQKms; rrenkert@8181: import org.dive4elements.river.exports.DiagramGenerator; rrenkert@8181: import org.dive4elements.river.exports.DischargeCurveGenerator; rrenkert@8181: import org.dive4elements.river.exports.StyledSeriesBuilder; rrenkert@8181: import org.dive4elements.river.exports.XYChartGenerator; rrenkert@8181: import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; rrenkert@8181: import org.dive4elements.river.jfree.RiverAnnotation; rrenkert@8181: import org.dive4elements.river.jfree.StickyAxisAnnotation; rrenkert@8181: import org.dive4elements.river.jfree.StyledXYSeries; rrenkert@8181: import org.dive4elements.river.themes.ThemeDocument; rrenkert@8181: rrenkert@8181: import org.jfree.chart.annotations.XYTextAnnotation; rrenkert@8181: rrenkert@8181: rrenkert@8181: /** Helper for data handling in discharge diagrams. */ rrenkert@8181: public class MiscDischargeProcessor rrenkert@8181: extends DefaultProcessor implements FacetTypes { rrenkert@8181: rrenkert@8181: private final static Logger logger = rrenkert@8181: Logger.getLogger(MiscDischargeProcessor.class); rrenkert@8181: rrenkert@8181: /** Station for which the diagram is shown. */ rrenkert@8181: private double km; rrenkert@8181: rrenkert@8181: /** Tolerance for comparison of kilometers. */ rrenkert@8181: public static final double KM_EPSILON = 0.001d; rrenkert@8181: rrenkert@8181: rrenkert@8181: /** This processor needs to be constructed with a given km. */ rrenkert@8181: public MiscDischargeProcessor() { rrenkert@8181: km = Double.NaN; rrenkert@8181: } rrenkert@8181: rrenkert@8181: rrenkert@8181: public MiscDischargeProcessor(double km) { rrenkert@8181: this.km = km; rrenkert@8181: } rrenkert@8181: rrenkert@8181: public void doOut( rrenkert@8181: DiagramGenerator generator, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible) { rrenkert@8181: CallContext context = generator.getCallContext(); rrenkert@8181: Object data = bundle.getData(context); rrenkert@8181: if (data instanceof WQKms) { rrenkert@8181: doWQKmsPointOut( rrenkert@8181: generator, (WQKms) data, bundle, theme, visible); rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: else if (data instanceof RiverAnnotation) { rrenkert@8181: doRiverAnnotationOut( rrenkert@8181: generator, (RiverAnnotation)data, bundle, theme, visible); rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: else if (data instanceof double[][]) { rrenkert@8181: doPointsOut(generator, (double[][])data, bundle, theme, visible); rrenkert@8181: } rrenkert@8181: else { rrenkert@8181: logger.error("Can't process " rrenkert@8181: + data.getClass().getName() + " objects of facet " rrenkert@8181: + bundle.getFacetName()); rrenkert@8181: } rrenkert@8181: } rrenkert@8181: rrenkert@8181: /** Process data, add it to plot. */ rrenkert@8181: @Override rrenkert@8181: public void doOut( rrenkert@8181: XYChartGenerator generator, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible, rrenkert@8181: int axisIndex rrenkert@8181: ) { rrenkert@8181: CallContext context = generator.getCallContext(); rrenkert@8181: Object data = bundle.getData(context); rrenkert@8181: /* TODO: Remove the first case.*/ rrenkert@8181: if (bundle.getFacetName().equals(STATIC_WQ)) { rrenkert@8181: doPointOut( rrenkert@8181: generator, bundle, theme, visible, axisIndex); rrenkert@8181: } rrenkert@8181: else if (data instanceof WQKms) { rrenkert@8181: doWQKmsPointOut( rrenkert@8181: generator, (WQKms) data, bundle, theme, visible, axisIndex); rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: else if (data instanceof RiverAnnotation) { rrenkert@8181: doRiverAnnotationOut( rrenkert@8181: generator, (RiverAnnotation) data, bundle, theme, visible); rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: else if (data instanceof double[][]) { rrenkert@8181: doMarksOut( rrenkert@8181: generator, (double[][]) data, bundle, theme, visible); rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: else { rrenkert@8181: logger.error("Can't process " rrenkert@8181: + data.getClass().getName() + " objects of facet " rrenkert@8181: + bundle.getFacetName()); rrenkert@8181: } rrenkert@8181: } rrenkert@8181: rrenkert@8181: private void doPointOut(XYChartGenerator generator, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible, rrenkert@8181: int axisIndex rrenkert@8181: ) { rrenkert@8181: XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme); rrenkert@8181: Object wq = bundle.getData(generator.getCallContext()); rrenkert@8181: if (wq instanceof double[][]) { rrenkert@8181: double [][] data = (double [][]) wq; rrenkert@8181: StyledSeriesBuilder.addPoints(series, data, true); rrenkert@8181: } else if (wq instanceof WQKms) { rrenkert@8181: WQKms wqkms = (WQKms) wq; rrenkert@8181: StyledSeriesBuilder.addPointsQW(series, (WQKms) wq); rrenkert@8181: } rrenkert@8181: rrenkert@8181: generator.addAxisSeries(series, axisIndex, visible); rrenkert@8181: } rrenkert@8181: rrenkert@8181: /** Handle WQKms data by finding w/q values at given km. */ rrenkert@8181: protected void doWQKmsPointOut(XYChartGenerator generator, rrenkert@8181: WQKms wqkms, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible, rrenkert@8181: int axidx rrenkert@8181: ) { rrenkert@8181: logger.debug("doWQKmsPointOut"); rrenkert@8181: String title = bundle.getFacetDescription(); rrenkert@8181: XYSeries series = new StyledXYSeries( rrenkert@8181: title, rrenkert@8181: theme); rrenkert@8181: rrenkert@8181: double[] kms = wqkms.getKms(); rrenkert@8181: rrenkert@8181: for (int i = 0 ; i< kms.length; i++) { rrenkert@8181: if (Math.abs(kms[i] - getKm()) <= KM_EPSILON) { rrenkert@8181: series.add(wqkms.getQ(i), wqkms.getW(i)); rrenkert@8181: generator.addAxisSeries(series, axidx, visible); rrenkert@8181: if(visible && theme.parseShowPointLabel()) { rrenkert@8181: List textAnnos = new ArrayList(); rrenkert@8181: XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( rrenkert@8181: title, rrenkert@8181: wqkms.getQ(i), rrenkert@8181: // TODO add a percentage to the extend of W axis rrenkert@8181: wqkms.getW(i)); rrenkert@8181: textAnnos.add(anno); rrenkert@8181: RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); rrenkert@8181: flysAnno.setTextAnnotations(textAnnos); rrenkert@8181: generator.addAnnotations(flysAnno); rrenkert@8181: } rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: } rrenkert@8181: rrenkert@8181: logger.warn("No WQ found for km " + getKm()); rrenkert@8181: } rrenkert@8181: rrenkert@8181: protected void doRiverAnnotationOut(XYChartGenerator generator, rrenkert@8181: RiverAnnotation annotations, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible rrenkert@8181: ) { rrenkert@8181: if (!(generator instanceof DischargeCurveGenerator)) { rrenkert@8181: logger.error("DischargeProcessor can only be used in " + rrenkert@8181: " in DischargeCurveGenerator-classes."); rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: logger.debug("doRiverAnnotationOut"); rrenkert@8181: DischargeCurveGenerator dGenerator = rrenkert@8181: (DischargeCurveGenerator) generator; rrenkert@8181: rrenkert@8181: dGenerator.translateRiverAnnotation(annotations); rrenkert@8181: dGenerator.doAnnotations( rrenkert@8181: annotations, rrenkert@8181: bundle, theme, visible); rrenkert@8181: } rrenkert@8181: rrenkert@8181: rrenkert@8181: /** rrenkert@8181: * Put Sticky Axis Markers to Y-axis for each value. rrenkert@8181: * @param data [[-,y1],[-,y2],...] ('x'-coordinates ignored) rrenkert@8181: */ rrenkert@8181: protected void doMarksOut(XYChartGenerator generator, rrenkert@8181: double[][] data, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible rrenkert@8181: ) { rrenkert@8181: logger.debug("doMarksOut"); rrenkert@8181: rrenkert@8181: if (!visible) { rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: rrenkert@8181: // TODO subtract gauge null point if at gauge. rrenkert@8181: String title = bundle.getFacetDescription(); rrenkert@8181: List yMarks = new ArrayList(); rrenkert@8181: rrenkert@8181: for (double yPos: data[1]) { rrenkert@8181: yMarks.add(new StickyAxisAnnotation( rrenkert@8181: title, rrenkert@8181: (float) yPos, rrenkert@8181: StickyAxisAnnotation.SimpleAxis.Y_AXIS)); rrenkert@8181: } rrenkert@8181: rrenkert@8181: generator.doAnnotations(new RiverAnnotation(title, yMarks), rrenkert@8181: bundle, theme, visible); rrenkert@8181: } rrenkert@8181: rrenkert@8181: /** True if this processor knows how to deal with facetType. */ rrenkert@8181: @Override rrenkert@8181: public boolean canHandle(String facetType) { rrenkert@8181: return STATIC_WQKMS_W.equals(facetType) rrenkert@8181: || COMPUTED_DISCHARGE_MAINVALUES_Q.equals(facetType) rrenkert@8181: || MAINVALUES_Q.equals(facetType) rrenkert@8181: || COMPUTED_DISCHARGE_MAINVALUES_W.equals(facetType) rrenkert@8181: || MAINVALUES_W.equals(facetType) rrenkert@8181: || STATIC_W_INTERPOL.equals(facetType) rrenkert@8181: || STATIC_WQ.equals(facetType) rrenkert@8181: || STATIC_WQ_ANNOTATIONS.equals(facetType); rrenkert@8181: } rrenkert@8181: rrenkert@8181: rrenkert@8181: /** The station of the current calculation/view. */ rrenkert@8181: protected double getKm() { rrenkert@8181: return km; rrenkert@8181: } rrenkert@8181: rrenkert@8181: private void doPointsOut( rrenkert@8181: DiagramGenerator generator, rrenkert@8181: double[][] data, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible rrenkert@8181: ) { rrenkert@8181: XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme); rrenkert@8181: StyledSeriesBuilder.addPoints(series, data, true); rrenkert@8181: generator.addAxisSeries(series, axisName, visible); rrenkert@8181: } rrenkert@8181: rrenkert@8181: /** Handle WQKms data by finding w/q values at given km. */ rrenkert@8181: protected void doWQKmsPointOut( rrenkert@8181: DiagramGenerator generator, rrenkert@8181: WQKms wqkms, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible rrenkert@8181: ) { rrenkert@8181: logger.debug("doWQKmsPointOut"); rrenkert@8181: String title = bundle.getFacetDescription(); rrenkert@8181: XYSeries series = new StyledXYSeries( rrenkert@8181: title, rrenkert@8181: theme); rrenkert@8181: rrenkert@8181: double[] kms = wqkms.getKms(); rrenkert@8181: rrenkert@8181: for (int i = 0 ; i< kms.length; i++) { rrenkert@8181: if (Math.abs(kms[i] - getKm()) <= KM_EPSILON) { rrenkert@8181: series.add(wqkms.getQ(i), wqkms.getW(i)); rrenkert@8181: generator.addAxisSeries(series, axisName, visible); rrenkert@8181: if(visible && theme.parseShowPointLabel()) { rrenkert@8181: List textAnnos = new ArrayList(); rrenkert@8181: XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( rrenkert@8181: title, rrenkert@8181: wqkms.getQ(i), rrenkert@8181: // TODO add a percentage to the extend of W axis rrenkert@8181: wqkms.getW(i)); rrenkert@8181: textAnnos.add(anno); rrenkert@8181: RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); rrenkert@8181: flysAnno.setTextAnnotations(textAnnos); rrenkert@8181: generator.addAnnotations(flysAnno); rrenkert@8181: } rrenkert@8181: return; rrenkert@8181: } rrenkert@8181: } rrenkert@8181: rrenkert@8181: logger.warn("No WQ found for km " + getKm()); rrenkert@8181: } rrenkert@8181: rrenkert@8181: protected void doRiverAnnotationOut(DiagramGenerator generator, rrenkert@8181: RiverAnnotation annotations, rrenkert@8181: ArtifactAndFacet bundle, rrenkert@8181: ThemeDocument theme, rrenkert@8181: boolean visible rrenkert@8181: ) { rrenkert@8181: if (visible) { rrenkert@8181: annotations.setTheme(theme); rrenkert@8181: generator.addAnnotations(annotations); rrenkert@8181: } rrenkert@8181: } rrenkert@8181: } rrenkert@8181: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :