view flys-artifacts/src/main/java/de/intevation/flys/exports/ATWriter.java @ 732:39d191f011dc

ATWriter: Results are now in cm. Made it more robust against corner cases. flys-artifacts/trunk@2224 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 23 Jun 2011 21:44:24 +0000
parents 078934923acb
children 65dcb5891206
line wrap: on
line source
package de.intevation.flys.exports;

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

import java.util.Locale;

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

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;

public class ATWriter
{
    private static Logger logger = Logger.getLogger(ATWriter.class);

    public static final int COLUMNS = 10;

    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 maxIndex = maxIncreasingWIndex(wq);

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

        double [] ws = new double[maxIndex+1];
        double [] qs = new double[ws.length];

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

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

        minW = wq.getW(0);
        maxW = wq.getW(maxIndex);
        minQ = wq.getQ(0);
        maxQ = wq.getQ(maxIndex);
    }

    public static int maxIncreasingWIndex(WQ wq) {

        int N = wq.size();

        if (N < 2) {
            return N-1;
        }

        double last = wq.getW(0);

        for (int i = 1; i < N; ++i) {
            double current = wq.getW(i);
            if (current <= last) {
                return i-1;
            }
        }

        return N-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;
        }
    }

    protected 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);
    }

    public void write(Writer writer) throws IOException {

        PrintWriter out = new PrintWriter(writer);

        double rest = Math.abs(minW % COLUMNS);

        double startW = Math.round(minW*10.0)/10.0;
        if (rest >= 1d) {
            startW -= 0.1;
            out.printf(Locale.US, "%8d", (int)Math.round(startW*100.0));
            int columns = (int)Math.floor(rest);
            for (int i = columns; i < COLUMNS; ++i) {
                out.print(EMPTY);
            }
            for (int i = COLUMNS-columns; i < COLUMNS; ++i) {
                printQ(out, getQ(startW + i*0.01));
            }
            out.println();
            startW += 0.1;
        }

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

            printQ(out, getQ(w));

            if (++col >= COLUMNS) {
                out.println();
                col = 0;
            }
        }

        if (col > 0) {
            out.println();
        }

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

http://dive4elements.wald.intevation.org