view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/AbstractSInfoCalculationResult.java @ 8940:82998242ba84

Preparing for additional outputs of SINFO-Tkh
author gernotbelger
date Tue, 06 Mar 2018 18:51:18 +0100
parents d9dbf0b74bc2
children 5d5d482da3e9
line wrap: on
line source
/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
 * Software engineering by
 *  Björnsen Beratende Ingenieure GmbH
 *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */
package org.dive4elements.river.artifacts.sinfo.common;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.dive4elements.river.artifacts.sinfo.tkhcalculation.SoilKind;
import org.dive4elements.river.artifacts.sinfo.util.WstInfo;

import gnu.trove.TDoubleArrayList;

/**
 * @author Gernot Belger
 */
public abstract class AbstractSInfoCalculationResult<ROW extends AbstractSInfoResultRow> implements Serializable {

    private static final long serialVersionUID = 1L;

    private final Collection<ROW> rows;

    private final String label;

    private final boolean hasTkh;

    private final WstInfo wst;

    public AbstractSInfoCalculationResult(final String label, final WstInfo wst, final boolean hasTkh, final Collection<ROW> rows) {
        this.label = label;
        this.wst = wst;
        this.hasTkh = hasTkh;
        this.rows = new ArrayList<>(rows);
    }

    public final String getLabel() {
        return this.label;
    }

    public final boolean hasTkh() {
        return this.hasTkh;
    }

    public final WstInfo getWst() {
        return this.wst;
    }

    public final void addRow(final ROW resultRow) {
        this.rows.add(resultRow);
    }

    public final Collection<ROW> getRows() {
        return Collections.unmodifiableCollection(this.rows);
    }

    public double[][] getFlowDepthPoints() {

        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());

        for (final ROW row : this.rows) {
            xPoints.add(row.getStation());
            yPoints.add(row.getFlowDepth());
        }

        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
    }

    public double[][] getFlowDepthTkhPoints() {

        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());

        for (final ROW row : this.rows) {
            xPoints.add(row.getStation());
            yPoints.add(row.getFlowDepthWithTkh());
        }

        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
    }

    public final double[][] getTkhUpPoints() {
        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
        final List<SoilKind> kinds = new ArrayList<>(this.rows.size());

        for (final ROW row : this.rows) {
            xPoints.add(row.getStation());
            yPoints.add(row.getTkhUp());
            kinds.add(row.getTkhKind());
        }

        return adjustTkhVisualization(xPoints, yPoints, kinds);
    }

    public final double[][] getTkhDownPoints() {
        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
        final List<SoilKind> kinds = new ArrayList<>(this.rows.size());

        for (final ROW row : this.rows) {
            xPoints.add(row.getStation());
            yPoints.add(row.getTkhDown());
            kinds.add(row.getTkhKind());
        }

        return adjustTkhVisualization(xPoints, yPoints, kinds);
    }

    public double[][] getVelocityPoints() {

        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());

        for (final ROW row : this.rows) {
            xPoints.add(row.getStation());
            yPoints.add(row.getVelocity());
        }

        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
    }

    public double[][] getD50Points() {

        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());

        for (final ROW row : this.rows) {
            xPoints.add(row.getStation());
            yPoints.add(row.getD50());
        }

        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
    }

    public double[][] getTauPoints() {

        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());

        for (final ROW row : this.rows) {
            xPoints.add(row.getStation());
            yPoints.add(row.getTau());
        }

        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
    }

    /**
     * the up and down points must be further adjusted for visualization, see Mail Hr. Reiß
     * basically we need to introduce extra points when the kind changes, so we get vertical lines in that case
     */
    private double[][] adjustTkhVisualization(final TDoubleArrayList xPoints, final TDoubleArrayList yPoints, final List<SoilKind> kinds) {

        final TDoubleArrayList adjustedX = new TDoubleArrayList(xPoints.size());
        final TDoubleArrayList adjustedY = new TDoubleArrayList(yPoints.size());

        adjustedX.add(xPoints.get(0));
        adjustedY.add(yPoints.get(0));

        for (int i = 1; i < xPoints.size(); i++) {

            final SoilKind kind1 = kinds.get(i - 1);
            final SoilKind kind2 = kinds.get(i);

            if (kind1 != kind2) {
                /* introduce two extra points in order to create a vertical line in the middle of the two adjacent points */
                final double x1 = xPoints.get(i - 1);
                final double y1 = yPoints.get(i - 1);
                final double x2 = xPoints.get(i);
                final double y2 = yPoints.get(i);

                final double middleX = (x1 + x2) / 2;

                // REMARK: we can't produce a 100% vertical line, as the area-renderer will not work correctly
                adjustedX.add(middleX - 0.0001);
                adjustedY.add(y1);

                adjustedX.add(middleX + 0.0001);
                adjustedY.add(y2);
            }

            /* always add the real point now */
            adjustedX.add(xPoints.get(i));
            adjustedY.add(yPoints.get(i));
        }

        return new double[][] { adjustedX.toNativeArray(), adjustedY.toNativeArray() };
    }
}

http://dive4elements.wald.intevation.org