# HG changeset patch # User Raimund Renkert # Date 1409925459 -7200 # Node ID 436512d9bd943318e1cdcefee78b5e7f659c315b # Parent 04d1d56d896b05bf11f55bba64bb7545dd23af70 Added processor for discharge curve in fixanalysis. diff -r 04d1d56d896b -r 436512d9bd94 artifacts/doc/conf/generators/discharge-diagram-defaults.xml --- a/artifacts/doc/conf/generators/discharge-diagram-defaults.xml Fri Sep 05 15:26:40 2014 +0200 +++ b/artifacts/doc/conf/generators/discharge-diagram-defaults.xml Fri Sep 05 15:57:39 2014 +0200 @@ -10,4 +10,5 @@ + diff -r 04d1d56d896b -r 436512d9bd94 artifacts/src/main/java/org/dive4elements/river/exports/process/FixWQProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FixWQProcessor.java Fri Sep 05 15:57:39 2014 +0200 @@ -0,0 +1,531 @@ +package org.dive4elements.river.exports.process; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.NamedDouble; +import org.dive4elements.river.artifacts.model.QWDDateRange; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.fixings.FixFunction; +import org.dive4elements.river.artifacts.model.fixings.FixWQCurveFacet; +import org.dive4elements.river.artifacts.model.fixings.QWD; +import org.dive4elements.river.artifacts.model.fixings.QWI; +import org.dive4elements.river.exports.DiagramGenerator; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.fixings.FixChartGenerator; +import org.dive4elements.river.exports.fixings.FixWQCurveGenerator; +import org.dive4elements.river.java2d.ShapeUtils; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.JFreeUtil; +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; +import org.jfree.chart.plot.Marker; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.data.xy.XYSeries; +import org.jfree.ui.RectangleAnchor; +import org.jfree.ui.RectangleInsets; +import org.jfree.ui.TextAnchor; + + +public class FixWQProcessor +extends DefaultProcessor +implements FacetTypes +{ + + private static Logger logger = Logger.getLogger(FixWQProcessor.class); + + public FixWQProcessor() { + } + + @Override + public void doOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + // TODO: Simplyfy this processor and move general facets/data to + // MiscDischargeProcessor or something... + String facetType = bundle.getFacetName(); + logger.debug("facet: " + facetType + " name: " + bundle.getFacetDescription()); + if(facetType.startsWith(FIX_SECTOR_AVERAGE_WQ)) { + doSectorAverageOut(generator, bundle, theme, visible); + } + else if(FIX_ANALYSIS_EVENTS_WQ.equals(facetType) + || FIX_REFERENCE_EVENTS_WQ.equals(facetType) + || FIX_EVENTS.equals(facetType)) { + doEventsOut(generator, bundle, theme, visible); + } + else if(FIX_WQ_CURVE.equals(facetType)) { + doWQCurveOut(generator, bundle, theme, visible); + } + else if(FIX_OUTLIER.equals(facetType)) { + doOutlierOut(generator, bundle, theme, visible); + } + else if(QSECTOR.equals(facetType)) { + doQSectorOut(generator, bundle, theme, visible); + } + else if(STATIC_WKMS_MARKS.equals(facetType) || + STATIC_WKMS.equals(facetType) || + HEIGHTMARKS_POINTS.equals(facetType) ) { + doWAnnotations(generator, bundle, theme, visible); + } + else if (LONGITUDINAL_W.equals(facetType) + || STATIC_WKMS_INTERPOL.equals(facetType) + || FIX_WQ_LS.equals(facetType)) { + doWQOut(generator, bundle, theme, visible); + } + } + + /** Add sector average points to chart. */ + protected void doSectorAverageOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + logger.debug("doSectorAverageOut"); + QWDDateRange qwdd = (QWDDateRange)bundle.getData(generator.getCallContext()); + QWD qwd = qwdd != null ? qwdd.getQWD() : null; + + if(qwd != null) { + XYSeries series = new StyledXYSeries( + bundle.getFacetDescription(), + false, true, + theme); + DateFormat dateFormat = DateFormat.getDateInstance( + DateFormat.SHORT); + + //TODO: W in cm at Gauge!!! + series.add(qwd.getQ(), qwd.getW(), false); + + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + dateFormat.format(qwd.getDate()), + qwd.getQ(), + qwd.getW()); + List annos = new ArrayList(); + annos.add(anno); + generator.addAxisSeries(series, axisName, visible); + + if (visible && theme != null && theme.parseShowPointLabel()) { + RiverAnnotation flysAnno = + new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(annos); + generator.addAnnotations(flysAnno); + } + } + else { + logger.debug("doSectorAverageOut: qwd == null"); + } + } + + + /** Add analysis event points to chart. */ + protected void doEventsOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + logger.debug("doAnalysisEventsOut"); + + QWD qwd = (QWD)bundle.getData(generator.getCallContext()); + + if (qwd == null) { + logger.debug("doAnalysisEventsOut: qwd == null"); + return; + } +// TODO: W in cm at Gauge!!! + //double gaugeDatum = getCurrentGaugeDatum(); + //boolean atGauge = gaugeDatum != 0d; + + //double factor = atGauge ? 100d : 1d; + + //double w = factor*(qwd.getW()-gaugeDatum); + + // Force empty symbol. + if (qwd.getInterpolated()) { + theme = new ThemeDocument(theme); // prevent potential side effects. + theme.setValue(ThemeDocument.USE_FILL_PAINT, "true"); + } + + XYSeries series = new StyledXYSeries( + bundle.getFacetDescription(), + theme, + qwd.getInterpolated() + ? ShapeUtils.INTERPOLATED_SHAPE + : ShapeUtils.MEASURED_SHAPE); + + series.add(qwd.getQ(), qwd.getW()); + + generator.addAxisSeries(series, axisName, visible); + + if (visible && theme.parseShowPointLabel()) { + + List textAnnos = new ArrayList(); + + DateFormat dateFormat = DateFormat.getDateInstance( + DateFormat.SHORT); + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + dateFormat.format(qwd.getDate()), + qwd.getQ(), + qwd.getW()); + textAnnos.add(anno); + + RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + generator.addAnnotations(flysAnno); + } + } + + /** Add reference event points to chart. */ + protected void doReferenceEventsOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible) { + logger.debug("doReferenceEventsOut"); + + QWI qwd = (QWI)bundle.getData(generator.getCallContext()); + if (qwd == null) { + logger.debug("doReferenceEventsOut: qwds == null in " + bundle.getFacetDescription()); + return; + } + + // Force empty symbol. + if (qwd.getInterpolated()) { + theme = new ThemeDocument(theme); // prevent potential side effects. + theme.setValue(ThemeDocument.USE_FILL_PAINT, "true"); + } + + XYSeries series = new StyledXYSeries( + bundle.getFacetDescription(), + false, true, theme, + qwd.getInterpolated() + ? ShapeUtils.INTERPOLATED_SHAPE + : ShapeUtils.MEASURED_SHAPE); + +// TODO: W in cm at gauge!!! + //double gaugeDatum = getCurrentGaugeDatum(); + //boolean atGauge = gaugeDatum != 0d; + + //double factor = atGauge ? 100d : 1d; + //double w = factor*(qwd.getW()-gaugeDatum); + + series.add(qwd.getQ(), qwd.getW(), false); + + if (visible && theme.parseShowPointLabel()) { + DateFormat dateFormat = DateFormat.getDateInstance( + DateFormat.SHORT); + + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + dateFormat.format(qwd.getDate()), + qwd.getQ(), + qwd.getW()); + + List textAnnos = new ArrayList(); + textAnnos.add(anno); + RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + generator.addAnnotations(flysAnno); + } + + generator.addAxisSeries(series, axisName, visible); + } + + protected void doWQCurveOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + logger.debug("doWQCurveOut"); + + FixWQCurveFacet facet = (FixWQCurveFacet)bundle.getFacet(); + FixFunction func = (FixFunction)facet.getData( + bundle.getArtifact(), generator.getCallContext()); + + if (func == null) { + logger.warn("doWQCurveOut: Facet does not contain FixFunction"); + return; + } + + double maxQ = func.getMaxQ(); + + if (maxQ > 0) { + StyledXYSeries series = JFreeUtil.sampleFunction2D( + func.getFunction(), + theme, + bundle.getFacetDescription(), + 500, // number of samples + 0.0 , // start + maxQ); // end + + //TODO: W in cm at gauge!!! +// double gaugeDatum = getCurrentGaugeDatum(); + +// if (gaugeDatum == 0d) { + generator.addAxisSeries(series, axisName, visible); +// } +/* else { + StyledXYSeries series2 = JFreeUtil.sampleFunction2D( + func.getFunction(), + doc, + aaf.getFacetDescription(), + 500, // number of samples + 0.0 , // start + maxQ); // end + addAxisSeries(series2, YAXIS.W.idx, false); + // Use second axis at cm if at gauge. + for (int i = 0, N = series.getItemCount(); i < N; i++) { + series.updateByIndex( + i, new Double(100d*(series.getY(i).doubleValue()-gaugeDatum))); + } + addAxisSeries(series, YAXIS.WCm.idx, visible); + }*/ + } + else { + logger.warn("doWQCurveOut: maxQ <= 0"); + } + } + + protected void doOutlierOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + logger.debug("doOutlierOut"); + + QWI[] qws = (QWI[])bundle.getData(generator.getCallContext()); + if(qws != null) { + XYSeries series = new StyledXYSeries( + bundle.getFacetDescription(), + false, true, + theme); + DateFormat dateFormat = DateFormat.getDateInstance( + DateFormat.SHORT); + + List annos = new ArrayList(); + //TODO: W in cm at Gauge!!! + for (QWI qw: qws) { + series.add(qw.getQ(), qw.getW(), false); + + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + dateFormat.format(qw.getDate()), + qw.getQ(), + qw.getW()); + annos.add(anno); + } + generator.addAxisSeries(series, axisName, visible); + + if (visible && theme != null && theme.parseShowPointLabel()) { + RiverAnnotation flysAnno = + new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(annos); + generator.addAnnotations(flysAnno); + } + } + else { + logger.debug("doOutlierOut: qwd == null"); + } + } + + /** Add markers for q sectors. */ + protected void doQSectorOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + logger.debug("doQSectorOut"); + if (!visible) { + return; + } + + Object qsectorsObj = bundle.getData(generator.getCallContext()); + if (qsectorsObj == null || !(qsectorsObj instanceof List)) { + logger.warn("No QSectors coming from data."); + return; + } + + List qsectorsList = (List) qsectorsObj; + if (qsectorsList.size() == 0 || !(qsectorsList.get(0) instanceof NamedDouble)) { + logger.warn("No QSectors coming from data."); + return; + } + + @SuppressWarnings("unchecked") + List qsectors = (List) qsectorsList; + + for (NamedDouble qsector : qsectors) { + if (Double.isNaN(qsector.getValue())) { + continue; + } + Marker m = new ValueMarker(qsector.getValue()); + m.setPaint(Color.black); + + float[] dashes = theme.parseLineStyle(); + int size = theme.parseLineWidth(); + BasicStroke stroke; + if (dashes.length <= 1) { + stroke = new BasicStroke(size); + } + else { + stroke = new BasicStroke(size, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_ROUND, + 1.0f, + dashes, + 0.0f); + } + m.setStroke(stroke); + + if (theme.parseShowLineLabel()) { + m.setLabel(qsector.getName()); + m.setPaint(theme.parseTextColor()); + m.setLabelFont(theme.parseTextFont()); + } + Color paint = theme.parseLineColorField(); + if (paint != null) { + m.setPaint(paint); + } + m.setLabelAnchor(RectangleAnchor.TOP_LEFT); + m.setLabelTextAnchor(TextAnchor.TOP_LEFT); + m.setLabelOffset(new RectangleInsets(5, 5, 10, 10)); + generator.addDomainMarker(m); + } + } + + /** + * Add W-Annotations to plot. + * @param wqkms actual data (double[][]). + * @param theme theme to use. + */ + protected void doWAnnotations( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + Object data = bundle.getData(generator.getCallContext()); + List xy = new ArrayList(); + if (data instanceof double[][]) { + logger.debug("Got double[][]"); + double [][] values = (double [][]) data; + for (int i = 0; i< values[0].length; i++) { + xy.add(new StickyAxisAnnotation(bundle.getFacetDescription(), + (float) values[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + } + + if (visible) { + generator.addAnnotations( + new RiverAnnotation( + bundle.getFacetDescription(), xy, null, theme)); + } + } + else { + // Assume its WKms. + logger.debug("Got WKms"); + /* TODO + WKms wkms = (WKms) data; + + Double ckm = + (Double) generator.getCallContext().getContextValue(FixChartGenerator.CURRENT_KM); + double location = (ckm != null) + ? ckm.doubleValue() + : getRange()[0]; + double w = StaticWKmsArtifact.getWAtKmLin(data, location); + xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), + (float) w, StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + + doAnnotations(new RiverAnnotation(facet.getDescription(), xy), + aandf, theme, visible);*/ + } + } + + /** + * Add WQ Data to plot. + * @param wqkms data as double[][] + */ + protected void doWQOut( + DiagramGenerator generator, + ArtifactAndFacet bundle, + ThemeDocument theme, + boolean visible + ) { + logger.debug("FixWQCurveGenerator: doWQOut"); + Object data = bundle.getData(generator.getCallContext()); + if (data instanceof WQKms) { + WQKms wqkms = (WQKms)data; + // TODO As in doEventsOut, the value-searching should + // be delivered by the facet already (instead of in the Generator). + logger.debug("FixWQCurveGenerator: doWQOut: WQKms"); + XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme); + // TODO: Remove dependency to FixChartGenerator. + Double ckm = (Double) generator.getCallContext().getContextValue(FixChartGenerator.CURRENT_KM); + if (wqkms == null || wqkms.getKms().length == 0 || ckm == null) { + logger.info("addPointFromWQKms: No event data to show."); + return; + } + double[] kms = wqkms.getKms(); + // TODO W in cm at gauge!!! + //double gaugeDatum = getCurrentGaugeDatum(); + //double factor = (gaugeDatum == 0d) ? 1d : 100d; + for (int i = 0 ; i< kms.length; i++) { + // TODO: Remove dependency to FixWQCurveGenerator. + if (Math.abs(kms[i] - ckm) <= FixWQCurveGenerator.EPSILON) { + series.add(wqkms.getQ(i), wqkms.getW(i), false); + generator.addAxisSeries(series, axisName, visible); + if(visible && theme.parseShowPointLabel()) { + List textAnnos = new ArrayList(); + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + bundle.getFacetDescription(), + wqkms.getQ(i), + wqkms.getW(i)); + textAnnos.add(anno); + RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + generator.addAnnotations(flysAnno); + } + return; + } + } + } + else { + logger.debug("FixWQCurveGenerator: doWQOut: double[][]"); + double [][] values = (double [][]) data; + + XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), false, true, theme); + StyledSeriesBuilder.addPoints(series, values, true); + + generator.addAxisSeries(series, axisName, visible); + } + } + + @Override + public boolean canHandle(String facettype) { + return facettype.startsWith(FIX_SECTOR_AVERAGE_WQ) + || FIX_ANALYSIS_EVENTS_WQ.equals(facettype) + || FIX_REFERENCE_EVENTS_WQ.equals(facettype) + || FIX_EVENTS.equals(facettype) + || FIX_WQ_CURVE.equals(facettype) + || FIX_OUTLIER.equals(facettype) + || QSECTOR.equals(facettype) + || STATIC_WKMS_MARKS.equals(facettype) + || STATIC_WKMS.equals(facettype) + || HEIGHTMARKS_POINTS.equals(facettype) + || LONGITUDINAL_W.equals(facettype) + || STATIC_WKMS_INTERPOL.equals(facettype) + || FIX_WQ_LS.equals(facettype); + } +}