# HG changeset patch # User dnt_bjoernsen # Date 1550157799 -3600 # Node ID 4b54d2ee728eec7fd59c3df7cde1bfa292344493 # Parent fd8f9e27af015592abea387799ea3d6839ff071f# Parent 6b2496d719361280e96bcb74a893cda9b7d432ce Merge diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/doc/conf/themes/default.xml --- a/artifacts/doc/conf/themes/default.xml Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/doc/conf/themes/default.xml Thu Feb 14 16:23:19 2019 +0100 @@ -2709,6 +2709,8 @@ + + diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/doc/conf/themes/second.xml --- a/artifacts/doc/conf/themes/second.xml Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/doc/conf/themes/second.xml Thu Feb 14 16:23:19 2019 +0100 @@ -2697,6 +2697,8 @@ + + diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java Thu Feb 14 16:23:19 2019 +0100 @@ -329,7 +329,7 @@ areas.add(Double.valueOf(0.0)); } if (chDepth - getFieldValue(i, BunduResultType.depthFields, j) > 0.0001) { - vExcav += computeMissingVolume(null, null, i, first, last, j, ExcavationMissingAreaComputer.Instance); + vExcav += computeMissingVolume(null, null, i, first, last, j, ExcavationMissingHeightComputer.Instance); } } final double[] meanBedVolumeArea = computeMeanBedMissingAreaAndVolume(i, first, last); @@ -352,13 +352,15 @@ final double dhCurr = heightcomputer.missingHeight(this.rows.get(current), current, first, last, field); final double dhPrev = heightcomputer.missingHeight(this.rows.get(current - 1), current - 1, first, last, field); final double dhNext = heightcomputer.missingHeight(this.rows.get(current + 1), current + 1, first, last, field); - final double kmCurr = missingKm(current); - final double kmPrev = missingKm(current - 1); - final double kmNext = missingKm(current + 1); + final double kmCurr = kmOfRow(current); + final double kmPrev = kmOfRow(current - 1); + final double kmNext = kmOfRow(current + 1); final double width = getFieldValue(current, BunduResultType.missWidthFields, field); - final double area1 = Double.isNaN(kmPrev) ? 0.0 : (0.25 * dhPrev + 0.75 * dhCurr) * width; - final double area2 = Double.isNaN(kmNext) ? 0.0 : (0.75 * dhCurr + 0.25 * dhNext) * width; - final double volume = Double.valueOf((Math.abs(kmCurr - kmPrev) * KM_TO_M / 2 * area1) + (Math.abs(kmNext - kmCurr) * KM_TO_M / 2 * area2)); + final double area1 = (0.25 * dhPrev + 0.75 * dhCurr) * width; + final double dist1 = Double.isNaN(kmPrev) ? 0.0 : Math.abs(kmCurr - kmPrev) * KM_TO_M / 2; + final double area2 = (0.75 * dhCurr + 0.25 * dhNext) * width; + final double dist2 = Double.isNaN(kmNext) ? 0.0 : Math.abs(kmNext - kmCurr) * KM_TO_M / 2; + final double volume = dist1 * area1 + dist2 * area2; if (volumes != null) volumes.add(volume); if (areas != null) { @@ -371,13 +373,17 @@ } /** - * Interface for the function that computes the missing height of a field + * Interface for the function that computes/gets the missing height of a field */ private interface MissingHeightComputer { /** - * Gets the missing area of a field and a row if in range, otherwise 0.0 + * Gets the missing height of a field and a row if in range, otherwise 0.0 */ double missingHeight(final ResultRow row, final int rowIndex, final int first, final int last, final int fieldIndex); + /** + * Gets the mean missing height of a row if in range, otherwise 0.0 + */ + double missingMeanHeight(final ResultRow row, final int rowIndex, final int first, final int last); } /** @@ -393,7 +399,21 @@ @Override public double missingHeight(final ResultRow row, final int rowIndex, final int first, final int last, final int fieldIndex) { if ((first <= rowIndex) && (rowIndex <= last)) { - return ((List) row.getValue(BunduResultType.missDepthFields)).get(fieldIndex - 1).doubleValue(); + final double dh = ((List) row.getValue(BunduResultType.missDepthFields)).get(fieldIndex - 1).doubleValue(); + return (!Double.isNaN(dh) ? dh : 0.0); + } + else + return 0.0; + } + + /** + * Gets the missing mean height of a row if in range, otherwise 0.0 + */ + @Override + public double missingMeanHeight(final ResultRow row, final int rowIndex, final int first, final int last) { + if ((first <= rowIndex) && (rowIndex <= last)) { + final double dh = row.getDoubleValue(BunduResultType.missDepthMeanBed); + return (!Double.isNaN(dh) ? dh : 0.0); } else return 0.0; @@ -403,8 +423,8 @@ /** * Computation of the excavation height of a field */ - private static class ExcavationMissingAreaComputer implements MissingHeightComputer { - public static MissingHeightComputer Instance = new ExcavationMissingAreaComputer(); + private static class ExcavationMissingHeightComputer implements MissingHeightComputer { + public static MissingHeightComputer Instance = new ExcavationMissingHeightComputer(); /** * Gets the excavation height of a field and a row if in range, otherwise 0.0 @@ -415,7 +435,21 @@ if ((first <= rowIndex) && (rowIndex <= last)) { final double channeldepth = row.getDoubleValue(BunduResultType.channelDepth) + EXCAVATION_DEPTH; final double fielddepth = ((List) row.getValue(BunduResultType.depthFields)).get(fieldIndex - 1).doubleValue(); - return (channeldepth - fielddepth); + return (!Double.isNaN(channeldepth - fielddepth) ? Math.max(channeldepth - fielddepth, 0.0) : 0.0); + } + else + return 0.0; + } + + /** + * Gets the excavation mean height of a row if in range, otherwise 0.0 + */ + @Override + public double missingMeanHeight(final ResultRow row, final int rowIndex, final int first, final int last) { + if ((first <= rowIndex) && (rowIndex <= last)) { + final double channeldepth = row.getDoubleValue(BunduResultType.channelDepth) + EXCAVATION_DEPTH; + final double flowdepth = row.getDoubleValue(BunduResultType.flowdepthMeanBed); + return (!Double.isNaN(channeldepth - flowdepth) ? Math.max(channeldepth - flowdepth, 0.0) : 0.0); } else return 0.0; @@ -427,41 +461,29 @@ */ private double[] computeMeanBedMissingAreaAndVolume(final int current, final int first, final int last) { - final double dhCurr = meanBedMissingHeight(current, first, last); + final double dhCurr = ActualMissingHeightComputer.Instance.missingMeanHeight(this.rows.get(current), current, first, last); if (dhCurr < 0.0001) return new double[] { 0.0, 0.0 }; - final double dhPrev = meanBedMissingHeight(current - 1, first, last); - final double dhNext = meanBedMissingHeight(current + 1, first, last); - final double kmCurr = missingKm(current); - final double kmPrev = missingKm(current - 1); - final double kmNext = missingKm(current + 1); + final double dhPrev = ActualMissingHeightComputer.Instance.missingMeanHeight(this.rows.get(current - 1), current - 1, first, last); + final double dhNext = ActualMissingHeightComputer.Instance.missingMeanHeight(this.rows.get(current + 1), current + 1, first, last); + final double kmCurr = kmOfRow(current); + final double kmPrev = kmOfRow(current - 1); + final double kmNext = kmOfRow(current + 1); final double width = this.rows.get(current).getDoubleValue(BunduResultType.channelWidth); - final double area1 = Double.isNaN(kmPrev) ? 0.0 : (0.25 * dhPrev + 0.75 * dhCurr) * width; - final double area2 = Double.isNaN(kmNext) ? 0.0 : (0.75 * dhCurr + 0.25 * dhNext) * width; - final double volume = Double.valueOf((Math.abs(kmCurr - kmPrev) * KM_TO_M / 2 * area1) + (Math.abs(kmNext - kmCurr) * KM_TO_M / 2 * area2)); - final double area = Double.isNaN(volume) ? Double.NaN : Double.valueOf(area1 + area2); + final double area1 = (0.25 * dhPrev + 0.75 * dhCurr) * width; + final double dist1 = Double.isNaN(kmPrev) ? 0.0 : Math.abs(kmCurr - kmPrev) * KM_TO_M / 2; + final double area2 = (0.75 * dhCurr + 0.25 * dhNext) * width; + final double dist2 = Double.isNaN(kmNext) ? 0.0 : Math.abs(kmNext - kmCurr) * KM_TO_M / 2; + final double volume = dist1 * area1 + dist2 * area2; + final double area = Double.isNaN(volume) ? Double.NaN : area1 + area2; return new double[] { volume, area }; } /** - * Gets the missing height of the mean bed level and a row if in range, otherwise 0.0 + * Gets the km of a row index if within range, otherwise NaN */ - private double meanBedMissingHeight(final int rowIndex, final int first, final int last) { - if ((first <= rowIndex) && (rowIndex <= last)) { - final double dh = this.rows.get(rowIndex).getDoubleValue(BunduResultType.channelDepth) - - this.rows.get(rowIndex).getDoubleValue(BunduResultType.flowdepthMeanBed); - if (dh > 0.0) - return dh; - return 0.0; - } - return 0.0; - } - - /** - * Gets the km of a row if within range, otherwise NaN - */ - private double missingKm(final int rowIndex) { - if ((0 <= rowIndex) && (rowIndex <= this.rows.size() - 1) && (this.rows.get(rowIndex).getValue(BunduResultType.hasMissingDepth) != null)) + private double kmOfRow(final int rowIndex) { + if ((0 <= rowIndex) && (rowIndex <= this.rows.size() - 1)) // && (this.rows.get(rowIndex).getValue(BunduResultType.hasMissingDepth) != null)) return this.rows.get(rowIndex).getDoubleValue(GeneralResultType.station); return Double.NaN; } diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/FlowDepthDevelopmentProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/FlowDepthDevelopmentProcessor.java Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/FlowDepthDevelopmentProcessor.java Thu Feb 14 16:23:19 2019 +0100 @@ -62,7 +62,7 @@ super(I18N_AXIS_LABEL, HANDLED_FACET_TYPES); } - protected SInfoResultType doGetType(final String facetName) { + private SInfoResultType doGetType(final String facetName) { if (FACET_FLOW_DEPTH_DEVELOPMENT_FILTERED.contentEquals(facetName)) return SInfoResultType.flowdepthDevelopment; @@ -111,6 +111,6 @@ @Override protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) { - return buildSeriesForType(generator, bundle, theme, visible, doGetType(bundle.getFacetName()), null); + return buildSeriesForType(generator, bundle, theme, visible, doGetType(bundle.getFacetName()), GAP_DISTANCE); } } \ No newline at end of file diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthChartExtender.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthChartExtender.java Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthChartExtender.java Thu Feb 14 16:23:19 2019 +0100 @@ -9,9 +9,6 @@ */ package org.dive4elements.river.artifacts.sinfo.flowdepth; -import java.awt.BasicStroke; -import java.awt.Stroke; - import org.dive4elements.river.exports.ChartExtender; import org.dive4elements.river.exports.DiagramGenerator; import org.jfree.chart.axis.ValueAxis; @@ -60,15 +57,6 @@ @Override public void afterGenerateChart(final DiagramGenerator generator, final XYPlot plot) { - final ValueAxis tkhAxis = generator.getAxis(TKH_AXIS); - if (tkhAxis != null) { - /* show baseline if tkhAxis is present */ - - // TODO: it would probably better to configure this via the ChartSettings, but currently no chart settings are loaded, - // so it is unclear if that feature still works. - final Stroke baselineStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - plot.setRangeZeroBaselineStroke(baselineStroke); - plot.setRangeZeroBaselineVisible(true); - } + /* nothing to do */ } } \ No newline at end of file diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Thu Feb 14 16:23:19 2019 +0100 @@ -19,15 +19,24 @@ import javax.swing.ImageIcon; import org.apache.log4j.Logger; +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.jfree.AxisDataset; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.jfree.RiverAnnotation; +import org.dive4elements.river.jfree.StyledAreaSeriesCollection; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; -import org.jfree.chart.LegendItem; import org.jfree.chart.annotations.XYAnnotation; import org.jfree.chart.annotations.XYImageAnnotation; import org.jfree.chart.annotations.XYTextAnnotation; +import org.jfree.chart.axis.LogarithmicAxis; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.axis.LogarithmicAxis; import org.jfree.chart.plot.Marker; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; @@ -36,21 +45,9 @@ import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.ui.RectangleInsets; import org.json.JSONArray; import org.json.JSONException; -import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; -import org.dive4elements.artifacts.CallContext; -import org.dive4elements.river.jfree.Bounds; -import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; -import org.dive4elements.river.jfree.DoubleBounds; -import org.dive4elements.river.jfree.RiverAnnotation; -import org.dive4elements.river.jfree.StyledAreaSeriesCollection; -import org.dive4elements.river.jfree.StyledXYSeries; -import org.dive4elements.river.jfree.AxisDataset; -import org.dive4elements.river.themes.ThemeDocument; - /** * An abstract base class for creating XY charts. @@ -385,7 +382,7 @@ return; } - AxisDataset axisDataset = (AxisDataset) getAxisDataset(index); + AxisDataset axisDataset = getAxisDataset(index); if (visible) { axisDataset.addDataset(area); @@ -484,11 +481,8 @@ DoubleBounds dBounds = (DoubleBounds) bounds; - if (dBounds == null - || Double.isNaN((Double) dBounds.getLower()) - || Double.isNaN((Double) dBounds.getUpper())) { + if ( Double.isNaN((Double) dBounds.getLower()) || Double.isNaN((Double) dBounds.getUpper())) return; - } Bounds old = getXBounds(index); @@ -509,11 +503,8 @@ DoubleBounds dBounds = (DoubleBounds) bounds; - if (dBounds == null - || Double.isNaN((Double) dBounds.getLower()) - || Double.isNaN((Double) dBounds.getUpper())) { + if ( Double.isNaN((Double) dBounds.getLower()) || Double.isNaN((Double) dBounds.getUpper())) return; - } Bounds old = getYBounds(index); @@ -631,7 +622,7 @@ return new Range(from, to); } catch (NumberFormatException nfe) { - log.warn("Wrong values for domain axis range."); + log.warn("Wrong values for domain axis range.", nfe); } } @@ -662,7 +653,7 @@ : new Range(from, to); } catch (NumberFormatException nfe) { - log.warn("Wrong values for value axis range."); + log.warn("Wrong values for value axis range.", nfe); } } @@ -910,7 +901,7 @@ XYSeries series = new StyledXYSeries(aandf.getFacetName(), seriesName, theme); // Add text annotations for single points. - List xy = new ArrayList(); + List xy = new ArrayList<>(); try { JSONArray points = new JSONArray((String) o); @@ -929,7 +920,7 @@ } } catch(JSONException e){ - log.error("Could not decode json."); + log.error("Could not decode json.", e); } RiverAnnotation annotations = diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java Thu Feb 14 16:23:19 2019 +0100 @@ -120,6 +120,7 @@ import org.jfree.chart.renderer.xy.AbstractXYItemRenderer; import org.jfree.chart.renderer.xy.XYItemRendererState; import org.jfree.chart.urls.XYURLGenerator; +import org.jfree.data.Range; import org.jfree.data.xy.DefaultXYDataset; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; @@ -196,6 +197,8 @@ /** Font to draw label of calculated area with. */ private Font labelFont; + private Color baseLineColor = null; + /** Whether or not to draw a label that shows the title of the theme. */ private boolean drawTitleLabel = false; @@ -304,6 +307,10 @@ this.labelBGColor = color; } + public void setBaseLineColor(final Color baseLineColor) { + this.baseLineColor = baseLineColor; + } + /** * Sets color that is used if drawOutline is true. */ @@ -1261,6 +1268,8 @@ // draw labels: only once per theme! drawAreaLabel(g2, dataArea, plot, domainAxis, rangeAxis); drawTitleLabel(g2, dataArea, info.getOwner().getEntityCollection(), dataset); + + drawZeroBaseline(g2, dataArea, plot, domainAxis, rangeAxis); } } @@ -1310,6 +1319,37 @@ } } + private void drawZeroBaseline(final Graphics2D g2, final Rectangle2D dataArea, final XYPlot plot, final ValueAxis domainAxis, final ValueAxis rangeAxis) { + + if (this.baseLineColor == null) + return; + + final PlotOrientation orientation = plot.getOrientation(); + final RectangleEdge domainAxisLocation = plot.getDomainAxisEdge(); + final RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); + + final Range domainRange = domainAxis.getRange(); + final double x0 = domainRange.getLowerBound(); + final double x1 = domainRange.getUpperBound(); + + final double screenX0 = domainAxis.valueToJava2D(x0, dataArea, domainAxisLocation); + final double screenX1 = domainAxis.valueToJava2D(x1, dataArea, domainAxisLocation); + final double screenY = rangeAxis.valueToJava2D(0.0, dataArea, rangeAxisLocation); + + Shape baseLine; + if (PlotOrientation.HORIZONTAL == orientation) + baseLine = new Line2D.Double(screenY, screenX0, screenY, screenX1); + else + baseLine = new Line2D.Double(screenX0, screenY, screenX1, screenY); + + if (baseLine.intersects(dataArea)) { + g2.setPaint(this.baseLineColor); + g2.setStroke(new BasicStroke(2)); + + g2.draw(baseLine); + } + } + /** * Draws the visual representation of a single data item, second pass. In * the second pass, the renderer draws the lines and shapes for the diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java Thu Feb 14 16:23:19 2019 +0100 @@ -144,6 +144,7 @@ applyShowLineLabel(renderer); applyPointStyle(renderer); applyShowMinimumMaximum(renderer); + applyBaseLineStyle(renderer); if (this.mode == FILL_MODE.UNDER) { renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA); } else if (this.mode == FILL_MODE.ABOVE) { @@ -168,6 +169,11 @@ // renderer.setIsMaximumShapeVisible(maximumVisible); } + private void applyBaseLineStyle(final StableXYDifferenceRenderer renderer) { + final Color c = this.theme.parseBaseLineColor(); + renderer.setBaseLineColor(c); + } + private void applyFillColor(final StableXYDifferenceRenderer renderer) { Paint paint = parseFillPaint(); diff -r fd8f9e27af01 -r 4b54d2ee728e artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java --- a/artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java Thu Feb 14 16:20:44 2019 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java Thu Feb 14 16:23:19 2019 +0100 @@ -124,6 +124,8 @@ public final static String SHOWEXTRAMARK = "showextramark"; + private final static String BASE_LINE_COLOR = "baselineColor"; + /* boolean parameter if the range of this theme should be considered when auto-zooming. Only works for area-series at the moment */ private static final String CALCULATE_RANGE = "calculateRange"; @@ -596,6 +598,10 @@ return parseInteger(getTransparencyString(), 50); } + public Color parseBaseLineColor() { + final String colorStr = getValue(BASE_LINE_COLOR); + return parseColor(colorStr); + } /** * Gets color from color field.