view flys-artifacts/src/main/java/de/intevation/flys/exports/ATWriter.java @ 5496:23d8f2700b38

Add support for multiple floodplains and add them to the datacage accordingly
author Andre Heinecke <aheinecke@intevation.de>
date Thu, 28 Mar 2013 12:39:14 +0100
parents a929d9a9fa1e
children
line wrap: on
line source
package de.intevation.flys.exports;

import java.io.IOException;
import java.io.Writer;
import java.io.PrintWriter;
import java.math.BigDecimal;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import de.intevation.artifacts.CallMeta;

import de.intevation.flys.artifacts.model.WQ;
import de.intevation.flys.artifacts.resources.Resources;

import org.apache.commons.math.analysis.UnivariateRealFunction;

import org.apache.commons.math.analysis.interpolation.SplineInterpolator;
import org.apache.commons.math.analysis.interpolation.LinearInterpolator;

import org.apache.commons.math.analysis.polynomials.PolynomialFunction;

import org.apache.commons.math.FunctionEvaluationException;

import org.apache.log4j.Logger;

/** Write AT files. */
public class ATWriter
{
    private static Logger logger = Logger.getLogger(ATWriter.class);

    public static final int COLUMNS = 10;

    public static final String I18N_AT_HEADER =
        "export.discharge.curve.at.header";

    public static final String I18N_AT_GAUGE_HEADER =
        "export.discharge.curve.at.gauge.header";

    public static final String EMPTY = "         ";

    protected double minW;
    protected double maxW;
    protected double minQ;
    protected double maxQ;

    protected UnivariateRealFunction qFunc;

    public ATWriter() {
    }

    public ATWriter(WQ wq) throws IllegalArgumentException {

        int [] bounds = wq.longestIncreasingWRangeIndices();

        if (logger.isDebugEnabled()) {
            logger.debug("exporting w between indices " +
                bounds[0] + " and " + bounds[1] + " (" +
                wq.getW(bounds[0]) + ", " + wq.getW(bounds[1]));
        }

        if (bounds[1]-bounds[0] < 1) { // Only first w can be written out.
            minW = maxW = wq.getW(bounds[0]);
            minQ = maxQ = wq.getQ(bounds[0]);
            // constant function
            qFunc = new PolynomialFunction(new double [] { minQ });
            return;
        }

        double [] ws = new double[bounds[1]-bounds[0]];
        double [] qs = new double[ws.length];

        for (int i = 0; i < ws.length; ++i) {
            int idx = bounds[0]+i;
            ws[i] = wq.getW(idx);
            qs[i] = wq.getQ(idx);
        }

        qFunc = ws.length < 3
            ? new LinearInterpolator().interpolate(ws, qs)
            : new SplineInterpolator().interpolate(ws, qs);

        minW = wq.getW(bounds[0]);
        maxW = wq.getW(bounds[1]);
        minQ = wq.getQ(bounds[0]);
        maxQ = wq.getQ(bounds[1]);
    }

    public double getQ(double w) {

        try {
            return qFunc.value(w);
        }
        catch (FunctionEvaluationException aode) {
            // should not happen
            logger.warn("spline interpolation failed", aode);
            return w <= minW ? minQ : maxQ;
        }
    }

    public static void printQ(PrintWriter out, double q) {
        String format;
             if (q <   1d) format = " % 8.3f";
        else if (q <  10d) format = " % 8.2f";
        else if (q < 100d) format = " % 8.1f";
        else {
            format = " % 8.0f";
            if (q > 1000d) q = Math.rint(q/10d)*10d;
        }
        out.printf(Locale.US, format, q);
    }


    protected static void printGaugeHeader(
        PrintWriter out,
        CallMeta    callMeta,
        String      river,
        double      km,
        String      gName,
        BigDecimal  datum,
        Date        date
    ) {
        DateFormat f = DateFormat.getDateInstance();
        out.print(Resources.getMsg(
            callMeta,
            I18N_AT_GAUGE_HEADER,
            I18N_AT_GAUGE_HEADER,
            new Object[] { river, gName, f.format(date), datum } ));
        out.print("\r\n");
    }

    protected static void printHeader(
        PrintWriter out,
        CallMeta    callMeta,
        String      river,
        double      km
    ) {
        out.print(Resources.getMsg(
            callMeta,
            I18N_AT_HEADER,
            I18N_AT_HEADER,
            new Object[] { river, km } ));
        out.print("\r\n");
    }

    public void write(
        Writer writer,
        CallMeta meta,
        String river,
        double km,
        String gName,
        BigDecimal datum,
        Date date,
        double scale)
    throws IOException
    {
        PrintWriter out = new PrintWriter(writer);

        // A header is required, because the desktop version of FLYS will skip
        // the first row.
        if (gName != null) {
            printGaugeHeader(out, meta, river, km, gName, datum, date);
        }
        else {
            printHeader(out, meta, river, km);
        }

        double rest = (minW * 100.0) % 10.0;

        double startW = Math.rint((minW - rest*0.01)*10.0)*0.1;

        if (logger.isDebugEnabled()) {
            logger.debug("startW: " + startW);
            logger.debug("rest: " + rest);
        }

        int col = 0;
        for (double w = startW; w <= maxW; w += 0.01) {
            if (col == 0) {
                out.printf(Locale.US, "%8d", (int)Math.round(w * scale));
            }

            if (w < minW) {
                out.print(EMPTY);
            }
            else {
                printQ(out, getQ(w));
            }

            if (++col >= COLUMNS) {
                out.print("\r\n");
                col = 0;
            }
        }

        if (col > 0) {
            out.print("\r\n");
        }

        out.flush();
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org