view flys-artifacts/src/main/java/de/intevation/flys/exports/ATWriter.java @ 5622:b28a6d05e969

Add a new mechanism in mapfish print call to add arbitary data maps Data properties are identified by starting with mapfish-data and they are then split in info value pairs where info can be the description of the information and value the value of the information to be transported in the data map.
author Andre Heinecke <aheinecke@intevation.de>
date Tue, 09 Apr 2013 19:04:32 +0200
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