gernotbelger@8854: /* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde gernotbelger@8877: * Software engineering by gernotbelger@8877: * Björnsen Beratende Ingenieure GmbH gernotbelger@8854: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt gernotbelger@8854: * gernotbelger@8854: * This file is Free Software under the GNU AGPL (>=v3) gernotbelger@8854: * and comes with ABSOLUTELY NO WARRANTY! Check out the gernotbelger@8854: * documentation coming with Dive4Elements River for details. gernotbelger@8854: */ gernotbelger@8854: package org.dive4elements.river.artifacts.sinfo.flowdepth; gernotbelger@8854: gernotbelger@8854: import java.io.Serializable; gernotbelger@8854: import java.util.ArrayList; gernotbelger@8854: import java.util.Collection; gernotbelger@8854: import java.util.Collections; gernotbelger@8886: import java.util.List; gernotbelger@8854: gernotbelger@8894: import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo; gernotbelger@8894: import org.dive4elements.river.artifacts.sinfo.util.WstInfo; gernotbelger@8894: gernotbelger@8854: import gnu.trove.TDoubleArrayList; gernotbelger@8854: gernotbelger@8854: /** gernotbelger@8854: * Contains the results of a {@link FlowDepthCalculation}. gernotbelger@8854: * gernotbelger@8854: * @author Gernot Belger gernotbelger@8854: */ gernotbelger@8886: class FlowDepthCalculationResult implements Serializable { gernotbelger@8854: gernotbelger@8877: private static final long serialVersionUID = 1L; gernotbelger@8854: gernotbelger@8877: private final Collection rows = new ArrayList<>(); gernotbelger@8854: gernotbelger@8877: private final String label; gernotbelger@8877: gernotbelger@8877: private final BedHeightInfo sounding; gernotbelger@8877: gernotbelger@8877: private final WstInfo wst; gernotbelger@8877: gernotbelger@8877: public FlowDepthCalculationResult(final String label, final WstInfo wst, final BedHeightInfo sounding) { gernotbelger@8877: this.label = label; gernotbelger@8877: this.wst = wst; gernotbelger@8877: this.sounding = sounding; gernotbelger@8877: } gernotbelger@8877: gernotbelger@8886: public void addRow(final double station, final double flowDepth, final double flowDepthWithTkh, final SoilKind tkhKind, final double tkh, gernotbelger@8886: final double tkhUp, final double tkhDown, final double waterlevel, final double discharge, final String waterlevelLabel, final String gauge, gernotbelger@8886: final double meanBedHeight, final String sondageLabel, final String location) { gernotbelger@8886: this.rows.add(new FlowDepthRow(station, flowDepth, flowDepthWithTkh, tkhKind, tkh, tkhUp, tkhDown, waterlevel, discharge, waterlevelLabel, gauge, gernotbelger@8886: meanBedHeight, sondageLabel, location)); gernotbelger@8877: } gernotbelger@8877: gernotbelger@8877: public String getLabel() { gernotbelger@8877: return this.label; gernotbelger@8877: } gernotbelger@8877: gernotbelger@8877: public WstInfo getWst() { gernotbelger@8877: return this.wst; gernotbelger@8877: } gernotbelger@8877: gernotbelger@8877: public BedHeightInfo getSounding() { gernotbelger@8877: return this.sounding; gernotbelger@8877: } gernotbelger@8877: gernotbelger@8877: public Collection getRows() { gernotbelger@8886: return Collections.unmodifiableCollection(this.rows); gernotbelger@8877: } gernotbelger@8877: gernotbelger@8854: public double[][] getFlowDepthPoints() { gernotbelger@8854: gernotbelger@8877: final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size()); gernotbelger@8877: final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size()); gernotbelger@8877: gernotbelger@8877: for (final FlowDepthRow row : this.rows) { gernotbelger@8877: xPoints.add(row.getStation()); gernotbelger@8877: yPoints.add(row.getFlowDepth()); gernotbelger@8877: } gernotbelger@8877: gernotbelger@8854: return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() }; gernotbelger@8854: } gernotbelger@8884: gernotbelger@8884: public double[][] getFlowDepthTkhPoints() { gernotbelger@8884: gernotbelger@8884: final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size()); gernotbelger@8884: final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size()); gernotbelger@8884: gernotbelger@8884: for (final FlowDepthRow row : this.rows) { gernotbelger@8884: xPoints.add(row.getStation()); gernotbelger@8884: yPoints.add(row.getFlowDepthWithTkh()); gernotbelger@8884: } gernotbelger@8884: gernotbelger@8884: return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() }; gernotbelger@8884: } gernotbelger@8884: gernotbelger@8886: public double[][] getTkhUpPoints() { gernotbelger@8884: final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size()); gernotbelger@8884: final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size()); gernotbelger@8886: final List kinds = new ArrayList<>(this.rows.size()); gernotbelger@8884: gernotbelger@8884: for (final FlowDepthRow row : this.rows) { gernotbelger@8884: xPoints.add(row.getStation()); gernotbelger@8886: yPoints.add(row.getTkhUp()); gernotbelger@8886: kinds.add(row.getTkhKind()); gernotbelger@8884: } gernotbelger@8884: gernotbelger@8886: return adjustTkhVisualization(xPoints, yPoints, kinds); gernotbelger@8886: } gernotbelger@8886: gernotbelger@8886: public double[][] getTkhDownPoints() { gernotbelger@8886: final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size()); gernotbelger@8886: final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size()); gernotbelger@8886: final List kinds = new ArrayList<>(this.rows.size()); gernotbelger@8886: gernotbelger@8886: for (final FlowDepthRow row : this.rows) { gernotbelger@8886: xPoints.add(row.getStation()); gernotbelger@8886: yPoints.add(row.getTkhDown()); gernotbelger@8886: kinds.add(row.getTkhKind()); gernotbelger@8886: } gernotbelger@8886: gernotbelger@8886: return adjustTkhVisualization(xPoints, yPoints, kinds); gernotbelger@8886: } gernotbelger@8886: gernotbelger@8886: /** gernotbelger@8886: * the up and down points must be further adjusted for visualization, see Mail Hr. Reiß gernotbelger@8886: * basically we need to introduce extra points when the kind changes, so we get vertical lines in that case gernotbelger@8886: */ gernotbelger@8886: private double[][] adjustTkhVisualization(final TDoubleArrayList xPoints, final TDoubleArrayList yPoints, final List kinds) { gernotbelger@8886: gernotbelger@8886: final TDoubleArrayList adjustedX = new TDoubleArrayList(xPoints.size()); gernotbelger@8886: final TDoubleArrayList adjustedY = new TDoubleArrayList(yPoints.size()); gernotbelger@8886: gernotbelger@8886: adjustedX.add(xPoints.get(0)); gernotbelger@8886: adjustedY.add(yPoints.get(0)); gernotbelger@8886: gernotbelger@8886: for (int i = 1; i < xPoints.size(); i++) { gernotbelger@8886: gernotbelger@8886: final SoilKind kind1 = kinds.get(i - 1); gernotbelger@8886: final SoilKind kind2 = kinds.get(i); gernotbelger@8886: gernotbelger@8886: if (kind1 != kind2) { gernotbelger@8886: /* introduce two extra points in order to create a vertical line in the middle of the two adjacent points */ gernotbelger@8886: final double x1 = xPoints.get(i - 1); gernotbelger@8886: final double y1 = yPoints.get(i - 1); gernotbelger@8886: final double x2 = xPoints.get(i); gernotbelger@8886: final double y2 = yPoints.get(i); gernotbelger@8886: gernotbelger@8886: final double middleX = (x1 + x2) / 2; gernotbelger@8886: gernotbelger@8886: // REMARK: we can't produce a 100% vertical line, as the area-renderer will not work correctly gernotbelger@8886: adjustedX.add(middleX - 0.0001); gernotbelger@8886: adjustedY.add(y1); gernotbelger@8886: gernotbelger@8886: adjustedX.add(middleX + 0.0001); gernotbelger@8886: adjustedY.add(y2); gernotbelger@8886: } gernotbelger@8886: gernotbelger@8886: /* always add the real point now */ gernotbelger@8886: adjustedX.add(xPoints.get(i)); gernotbelger@8886: adjustedY.add(yPoints.get(i)); gernotbelger@8886: } gernotbelger@8886: gernotbelger@8886: gernotbelger@8886: return new double[][] { adjustedX.toNativeArray(), adjustedY.toNativeArray() }; gernotbelger@8884: } gernotbelger@8854: }