sascha@729: package de.intevation.flys.exports;
sascha@729: 
sascha@729: import java.io.IOException;
sascha@729: import java.io.Writer;
sascha@729: import java.io.PrintWriter;
sascha@729: 
sascha@729: import java.util.Locale;
sascha@729: 
sascha@729: import de.intevation.flys.artifacts.model.WQ;
sascha@729: 
sascha@732: import org.apache.commons.math.analysis.UnivariateRealFunction;
sascha@729: 
sascha@732: import org.apache.commons.math.analysis.interpolation.SplineInterpolator;
sascha@732: import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
sascha@729: 
sascha@732: import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
sascha@732: 
sascha@732: import org.apache.commons.math.FunctionEvaluationException;
sascha@729: 
sascha@729: import org.apache.log4j.Logger;
sascha@729: 
sascha@729: public class ATWriter
sascha@729: {
sascha@729:     private static Logger logger = Logger.getLogger(ATWriter.class);
sascha@729: 
sascha@729:     public static final int COLUMNS = 10;
sascha@729: 
sascha@732:     public static final String EMPTY = "         ";
sascha@729: 
sascha@729:     protected double minW;
sascha@729:     protected double maxW;
sascha@729:     protected double minQ;
sascha@729:     protected double maxQ;
sascha@729: 
sascha@732:     protected UnivariateRealFunction qFunc;
sascha@729: 
sascha@729:     public ATWriter() {
sascha@729:     }
sascha@729: 
sascha@729:     public ATWriter(WQ wq) throws IllegalArgumentException {
sascha@729: 
sascha@1033:         int [] bounds = wq.longestIncreasingWRangeIndices();
sascha@729: 
sascha@1033:         if (logger.isDebugEnabled()) {
sascha@1033:             logger.debug("exporting w between indices " +
sascha@1033:                 bounds[0] + " and " + bounds[1] + " (" +
sascha@1033:                 wq.getW(bounds[0]) + ", " + wq.getW(bounds[1]));
sascha@1033:         }
sascha@1033: 
sascha@1033:         if (bounds[1]-bounds[0] < 1) { // Only first w can be written out.
sascha@1033:             minW = maxW = wq.getW(bounds[0]);
sascha@1033:             minQ = maxQ = wq.getQ(bounds[0]);
sascha@732:             // constant function
sascha@732:             qFunc = new PolynomialFunction(new double [] { minQ });
sascha@729:             return;
sascha@729:         }
sascha@729: 
sascha@1033:         double [] ws = new double[bounds[1]-bounds[0]];
sascha@729:         double [] qs = new double[ws.length];
sascha@729: 
sascha@729:         for (int i = 0; i < ws.length; ++i) {
sascha@1033:             int idx = bounds[0]+i;
sascha@1033:             ws[i] = wq.getW(idx);
sascha@1033:             qs[i] = wq.getQ(idx);
sascha@729:         }
sascha@729: 
sascha@732:         qFunc = ws.length < 3
sascha@732:             ? new LinearInterpolator().interpolate(ws, qs)
sascha@732:             : new SplineInterpolator().interpolate(ws, qs);
sascha@729: 
sascha@1033:         minW = wq.getW(bounds[0]);
sascha@1033:         maxW = wq.getW(bounds[1]);
sascha@1033:         minQ = wq.getQ(bounds[0]);
sascha@1033:         maxQ = wq.getQ(bounds[1]);
sascha@729:     }
sascha@729: 
sascha@729:     public double getQ(double w) {
sascha@729: 
sascha@729:         try {
sascha@729:             return qFunc.value(w);
sascha@729:         }
sascha@732:         catch (FunctionEvaluationException aode) {
sascha@729:             // should not happen
sascha@729:             logger.warn("spline interpolation failed", aode);
sascha@729:             return w <= minW ? minQ : maxQ;
sascha@729:         }
sascha@729:     }
sascha@729: 
sascha@729:     protected static void printQ(PrintWriter out, double q) {
sascha@729:         String format;
sascha@732:              if (q <   1d) format = " % 8.3f";
sascha@732:         else if (q <  10d) format = " % 8.2f";
sascha@732:         else if (q < 100d) format = " % 8.1f";
sascha@729:         else {
sascha@729:             format = " % 8.0f";
sascha@732:             if (q > 1000d) q = Math.rint(q/10d)*10d;
sascha@729:         }
sascha@729:         out.printf(Locale.US, format, q);
sascha@729:     }
sascha@729: 
sascha@729:     public void write(Writer writer) throws IOException {
sascha@729: 
sascha@729:         PrintWriter out = new PrintWriter(writer);
sascha@729: 
sascha@732:         double rest = Math.abs(minW % COLUMNS);
sascha@729: 
sascha@732:         double startW = Math.round(minW*10.0)/10.0;
sascha@729:         if (rest >= 1d) {
sascha@732:             startW -= 0.1;
sascha@732:             out.printf(Locale.US, "%8d", (int)Math.round(startW*100.0));
sascha@729:             int columns = (int)Math.floor(rest);
sascha@729:             for (int i = columns; i < COLUMNS; ++i) {
sascha@729:                 out.print(EMPTY);
sascha@729:             }
sascha@732:             for (int i = COLUMNS-columns; i < COLUMNS; ++i) {
sascha@732:                 printQ(out, getQ(startW + i*0.01));
sascha@729:             }
sascha@732:             out.println();
sascha@732:             startW += 0.1;
sascha@729:         }
sascha@729: 
sascha@729:         int col = 0;
sascha@732:         for (double w = startW; w <= maxW; w += 0.01) {
sascha@732:             if (col == 0) {
sascha@732:                 out.printf(Locale.US, "%8d", (int)Math.round(w*100.0));
sascha@732:             }
sascha@729: 
sascha@729:             printQ(out, getQ(w));
sascha@729: 
sascha@729:             if (++col >= COLUMNS) {
sascha@729:                 out.println();
sascha@729:                 col = 0;
sascha@729:             }
sascha@729:         }
sascha@729: 
sascha@729:         if (col > 0) {
sascha@729:             out.println();
sascha@729:         }
sascha@729: 
sascha@729:         out.flush();
sascha@729:     }
sascha@729: }
sascha@729: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :