Mercurial > dive4elements > river
diff artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java @ 9450:7e1fb8d0cb0d
Bundu bzws calculation nearly completed, some corrections with csv output, started with linking the minfo density calculation
author | mschaefer |
---|---|
date | Wed, 22 Aug 2018 19:12:51 +0200 |
parents | d32b11d585cd |
children | fd6621f47a72 |
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java Wed Aug 22 14:07:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java Wed Aug 22 19:12:51 2018 +0200 @@ -11,6 +11,7 @@ package org.dive4elements.river.artifacts.bundu.bezugswst; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; import org.dive4elements.artifacts.CallContext; @@ -57,11 +58,16 @@ private final List<ResultRow> rows; + private Double missKmFrom; + + private Double missKmTo; + public BezugswstCalculation(final CallContext context) { this.context = context; this.rows = new ArrayList<>(); } + /** * Calculates the result rows of a bundu bzws workflow */ @@ -77,8 +83,8 @@ final int startYear = access.getStartYear(); final int endYear = access.getBezugsJahr(); final Integer ud = access.getUd(); - final Double missingVolFrom = access.getMissingVolFrom(); - final Double missingVolTo = access.getMissingVolTo(); + this.missKmFrom = access.getMissingVolFrom(); + this.missKmTo = access.getMissingVolTo(); final BezugswstCalculationResults results = new BezugswstCalculationResults(calcModeLabel, user, riverInfo, access.getRange()); @@ -113,15 +119,22 @@ // Compute the missing volumes if (access.isCalculateMissingValue()) { - computeMissingVolumes(access.getMissingVolFrom().doubleValue(), access.getMissingVolTo().doubleValue(), problems); - // TODO Lagerungsdichte holen/berechnen (density) und Massen berechnen + computeMissingVolumes(problems); + final BedQualityCalculator bqCalculator = new BedQualityCalculator(this.context, bunduartifact); + final double[] kms = new double[] { this.missKmFrom.doubleValue(), this.missKmTo.doubleValue() }; + final Calendar endDay = Calendar.getInstance(); + endDay.set(access.getBezugsJahr().intValue(), 11, 31); + final Calendar startDay = Calendar.getInstance(); + startDay.set(endDay.get(Calendar.YEAR) - 20, 0, 1); + // TODO final double[][] kmDensities = bqCalculator.execute(problems, river, kms, startDay.getTime(), endDay.getTime()); + computeMissingMasses(problems); } // Add the result to the results collection final WaterlevelDescriptionBuilder descBuilder = new WaterlevelDescriptionBuilder(winfo, this.context); final String qtext = descBuilder.getMetadataQ(); final BezugswstMainCalculationResult result = new BezugswstMainCalculationResult("bundu-bzws", this.rows, bedHeightsFinder.getInfo(), wstInfo, - access.getFunction(), preprocessing, startYear, endYear, ud, qtext, wqkms, missingVolFrom, missingVolTo); + access.getFunction(), preprocessing, startYear, endYear, ud, qtext, wqkms, this.missKmFrom, this.missKmTo); results.addResult(result, problems); // Create the missing volume results @@ -131,12 +144,13 @@ results.addResult(r1, null); final String title2 = Resources.getMsg(this.context.getMeta(), "bundu.export.csv.title.bezugswst.result2"); - final BezugswstMissVolCalculationResult2 r2 = new BezugswstMissVolCalculationResult2(title2, this.rows); + final List<ResultRow> rows2 = copyMissRows(); + final BezugswstMissVolCalculationResult2 r2 = new BezugswstMissVolCalculationResult2(title2, rows2); results.addResult(r2, null); final String title3 = Resources.getMsg(this.context.getMeta(), "bundu.export.csv.title.bezugswst.result3"); final List<ResultRow> totalRows = new ArrayList<>(); - totalRows.add(createTotalsRow(missingVolFrom.doubleValue(), missingVolTo.doubleValue(), problems)); + totalRows.add(createTotalsRow(problems)); final BezugswstMissVolCalculationResult3 r3 = new BezugswstMissVolCalculationResult3(title3, totalRows); results.addResult(r3, null); } @@ -179,6 +193,7 @@ row.putValue(GeneralResultType.waterlevelLabel, wstInfo.getLabel()); row.putValue(GeneralResultType.gaugeLabel, riverInfoProv.findGauge(station)); row.putValue(GeneralResultType.location, riverInfoProv.getLocation(station)); + row.putValue(BunduResultType.sounding, bedHeightsFinder.getInfo().getDescription()); // Set bed and channel bottom height final double msh = bedHeightsFinder.getMeanBedHeight(station); @@ -197,12 +212,19 @@ row.putValue(BunduResultType.channelLowerEdge, channelHeight); final double channelWidth = channelFinder.getWidth(station); row.putValue(BunduResultType.channelWidth, channelWidth); + if (!Double.isNaN(channelHeight)) { + if (msh > channelHeight + 0.001) + row.putValue(BunduResultType.missDepthMeanBed, msh - channelHeight); + else + row.putValue(BunduResultType.missDepthMeanBed, 0.0); + } // Set field heights and missing heights final List<Double> fieldHeights = new ArrayList<>(); final List<Double> fieldDepths = new ArrayList<>(); final List<Double> fieldMissDepths = new ArrayList<>(); final List<Double> fieldMissWidths = new ArrayList<>(); + final List<Double> fieldNulls = new ArrayList<>(); int missFieldCnt = 0; for (int i = BedHeightValueType.FIELD_FIRST_INDEX; i <= BedHeightValueType.FIELD_LAST_INDEX; i++) { final double h = bedHeightsFinder.getFieldHeight(station, i); @@ -216,10 +238,20 @@ fieldMissDepths.add(Double.valueOf(0.0)); fieldMissWidths.add(Double.valueOf(0.0)); } + fieldNulls.add(Double.NaN); } - row.putValue(BunduResultType.missDepthFields, fieldMissDepths); - row.putValue(BunduResultType.missWidthFields, fieldMissWidths); - row.putValue(BunduResultType.hasMissingDepth, (missFieldCnt >= 1)); + if (isKmInMissingVolumeRange(station)) { + row.putValue(BunduResultType.missDepthFields, fieldMissDepths); + row.putValue(BunduResultType.missWidthFields, fieldMissWidths); + row.putValue(BunduResultType.hasMissingDepth, (missFieldCnt >= 1)); + } + else { + row.putValue(BunduResultType.missDepthFields, fieldNulls); + row.putValue(BunduResultType.missWidthFields, fieldNulls); + row.putValue(BunduResultType.hasMissingDepth, null); + } + row.putValue(BunduResultType.missVolumeFields, fieldNulls); + row.putValue(BunduResultType.missMassFields, fieldNulls); row.putValue(BunduResultType.bedHeightFields, fieldHeights); row.putValue(BunduResultType.depthFields, fieldDepths); @@ -240,11 +272,11 @@ /** * Computes the missing volumes in a km range */ - private void computeMissingVolumes(final double kmFrom, final double kmTo, final Calculation problems) { + private void computeMissingVolumes(final Calculation problems) { // Search start km int first = -1; for (int j = 0; j <= this.rows.size() - 1; j++) { - if (this.rows.get(j).getDoubleValue(GeneralResultType.station) > kmFrom - 0.0001) { + if (isKmInMissingVolumeRange(this.rows.get(j).getDoubleValue(GeneralResultType.station))) { first = j; break; } @@ -252,36 +284,33 @@ if (first < 0) return; int last = this.rows.size() - 1; - int i = first; - while (i <= this.rows.size() - 1) { - if (this.rows.get(i).getDoubleValue(GeneralResultType.station) > kmTo + 0.0001) + for (int i = first; i <= this.rows.size() - 1; i++) { + if (!isKmInMissingVolumeRange(this.rows.get(i).getDoubleValue(GeneralResultType.station))) break; - if (this.rows.get(i).getDoubleValue(GeneralResultType.station) > kmTo - 0.0001) + if (this.rows.get(i).getDoubleValue(GeneralResultType.station) > this.missKmTo.doubleValue() - 0.0001) last = i; final List<Double> areas = new ArrayList<>(); final List<Double> volumes = new ArrayList<>(); double vTotal = 0.0; double vExcav = 0.0; - double expenses = 0.0; for (int j = BedHeightValueType.FIELD_FIRST_INDEX; j <= BedHeightValueType.FIELD_LAST_INDEX; j++) { if (getFieldValue(i, BunduResultType.missDepthFields, j) > 0.0001) { computeMissingVolume(volumes, areas, i, first, last, j); vTotal += volumes.get(j - 1); vExcav += volumes.get(j - 1) + areas.get(j - 1) * EXCAVATION_DEPTH; - expenses += vExcav * EXPENSE_PER_CBM; } else { volumes.add(Double.valueOf(0.0)); areas.add(Double.valueOf(0.0)); } } + final double[] meanBedVolumeArea = computeMeanBedMissingAreaAndVolume(i, first, last); + this.rows.get(i).putValue(BunduResultType.missVolumeMeanBed, meanBedVolumeArea[0]); + this.rows.get(i).putValue(BunduResultType.missAreaMeanBed, meanBedVolumeArea[1]); this.rows.get(i).putValue(BunduResultType.missVolumeFields, volumes); - // TODO: berechnete masse hier einfügen! - this.rows.get(i).putValue(BunduResultType.missMassFields, volumes); this.rows.get(i).putValue(BunduResultType.missAreaFields, areas); this.rows.get(i).putValue(BunduResultType.missVolumeTotal, vTotal); this.rows.get(i).putValue(BunduResultType.excavationVolume, vExcav); - this.rows.get(i).putValue(BunduResultType.excavationCosts, expenses); - i++; + this.rows.get(i).putValue(BunduResultType.excavationCosts, vExcav * EXPENSE_PER_CBM); } } @@ -290,21 +319,21 @@ */ private void computeMissingVolume(final List<Double> volumes, final List<Double> areas, final int current, final int first, final int last, final int field) { + final double areaCurr = missingArea(current, first, last, field); final double areaPrev = missingArea(current - 1, first, last, field); final double areaNext = missingArea(current + 1, first, last, field); final double kmCurr = missingKm(current); final double kmPrev = missingKm(current - 1); final double kmNext = missingKm(current + 1); - if (Double.isNaN(kmPrev) || Double.isNaN(kmNext)) { - volumes.add(Double.valueOf(0.0)); - areas.add(Double.valueOf(0.0)); - } else { - final double area1 = 0.5 * (areaCurr + areaPrev); - final double area2 = 0.5 * (areaCurr + areaNext); - volumes.add(Double.valueOf((Math.abs(kmCurr - kmPrev) * 0.5 * area1) + (Math.abs(kmNext - kmCurr) * 0.5 * area2))); + final double area1 = Double.isNaN(kmPrev) ? 0.0 : 0.5 * (areaCurr + areaPrev); + final double area2 = Double.isNaN(kmNext) ? 0.0 : 0.5 * (areaCurr + areaNext); + final double volume = Double.valueOf((Math.abs(kmCurr - kmPrev) * 500 * area1) + (Math.abs(kmNext - kmCurr) * 500 * area2)); + volumes.add(volume); + if (!Double.isNaN(volume)) areas.add(Double.valueOf(area1 + area2)); - } + else + areas.add(Double.NaN); } /** @@ -318,13 +347,69 @@ } /** + * Computes the missing area and volume of the mean bed height of a km row + */ + private double[] computeMeanBedMissingAreaAndVolume(final int current, final int first, final int last) { + + final double areaCurr = meanBedMissingArea(current, first, last); + final double areaPrev = meanBedMissingArea(current - 1, first, last); + final double areaNext = meanBedMissingArea(current + 1, first, last); + final double kmCurr = missingKm(current); + final double kmPrev = missingKm(current - 1); + final double kmNext = missingKm(current + 1); + final double area1 = Double.isNaN(kmPrev) ? 0.0 : 0.5 * (areaCurr + areaPrev); + final double area2 = Double.isNaN(kmNext) ? 0.0 : 0.5 * (areaCurr + areaNext); + final double volume = Double.valueOf((Math.abs(kmCurr - kmPrev) * 500 * area1) + (Math.abs(kmNext - kmCurr) * 500 * area2)); + final double area = Double.isNaN(volume) ? Double.NaN : Double.valueOf(area1 + area2); + return new double[] { volume, area }; + } + + /** + * Gets the missing area of the mean bed height and a row if in range, otherwise 0.0 + */ + private double meanBedMissingArea(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(SInfoResultType.flowdepth); + if (dh > 0.0) + return dh * this.rows.get(rowIndex).getDoubleValue(BunduResultType.channelWidth); + 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)) return this.rows.get(rowIndex).getDoubleValue(GeneralResultType.station); - else - return Double.NaN; + return Double.NaN; + } + + /** + * Computes the missing masses + */ + private void computeMissingMasses(final Calculation problems) { + for (final ResultRow row : this.rows) { + @SuppressWarnings("unchecked") + final List<Double> volumes = (List<Double>) row.getValue(BunduResultType.missVolumeFields); + if ((volumes == null) || Double.isNaN(volumes.get(0))) + continue; + final double density = getDensity(row.getDoubleValue(GeneralResultType.station)); + final List<Double> masses = new ArrayList<>(); + double kmTotal = 0.0; + for (int j = BedHeightValueType.FIELD_FIRST_INDEX; j <= BedHeightValueType.FIELD_LAST_INDEX; j++) { + final double m = volumes.get(j - 1) * density; + masses.add(m); + if (!Double.isNaN(m)) + kmTotal += m; + } + row.putValue(BunduResultType.density, density); + row.putValue(BunduResultType.missMassFields, masses); + row.putValue(BunduResultType.missMassTotal, kmTotal); + row.putValue(BunduResultType.missMassMeanBed, row.getDoubleValue(BunduResultType.missVolumeMeanBed) * density); + } } /** @@ -344,23 +429,57 @@ /** * Computes the volume and mass total of all rows with missing volumes */ - private ResultRow createTotalsRow(final double kmFrom, final double kmTo, final Calculation problems) { + private ResultRow createTotalsRow(final Calculation problems) { // Search start km double vTotal = 0.0; double mTotal = 0.0; + double eTotal = 0.0; + double cTotal = 0.0; for (final ResultRow row : this.rows) { - final double volume = row.getDoubleValue(BunduResultType.missVolumeMeanBed); - final double mass = row.getDoubleValue(BunduResultType.missMassMeanBed); + final double volume = row.getDoubleValue(BunduResultType.missVolumeTotal); + final double mass = row.getDoubleValue(BunduResultType.missMassTotal); + final double excavation = row.getDoubleValue(BunduResultType.excavationVolume); + final double costs = row.getDoubleValue(BunduResultType.excavationCosts); if (!Double.isNaN(volume) && !Double.isNaN(mass)) { vTotal += volume; mTotal += mass; + eTotal += excavation; + cTotal += costs; } } final ResultRow sumRow = ResultRow.create(); - sumRow.putValue(BunduResultType.missStationRangeFrom, Double.valueOf(kmFrom)); - sumRow.putValue(BunduResultType.missStationRangeTo, Double.valueOf(kmTo)); + sumRow.putValue(BunduResultType.missStationRangeFrom, Double.valueOf(this.missKmFrom)); + sumRow.putValue(BunduResultType.missStationRangeTo, Double.valueOf(this.missKmTo)); sumRow.putValue(BunduResultType.missVolumeTotal, vTotal); sumRow.putValue(BunduResultType.missMassTotal, mTotal); + // TODO sumRow.putValue(BunduResultType.excavationVolumeTotal, eTotal); + // TODO sumRow.putValue(BunduResultType.excavationCostsTotal, cTotal); return sumRow; } + + /** + * Copies the rows of the missing volume calculation range into a new list + */ + private List<ResultRow> copyMissRows() { + final List<ResultRow> missRows = new ArrayList<>(); + for (final ResultRow row : this.rows) { + final double km = row.getDoubleValue(GeneralResultType.station); + if (isKmInMissingVolumeRange(km)) + missRows.add(row); + } + return missRows; + } + + private double getDensity(final double km) { + return 1.73; // TODO + } + + /** + * Checks whether a km lies in the missing volume calculation range + */ + private boolean isKmInMissingVolumeRange(final double km) { + if ((this.missKmFrom == null) || (this.missKmTo == null)) + return false; + return (this.missKmFrom.doubleValue() - 0.0001 < km) && (km < this.missKmTo.doubleValue() + 0.0001); + } } \ No newline at end of file