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: ingo@1658: import de.intevation.artifacts.CallMeta; ingo@1658: sascha@729: import de.intevation.flys.artifacts.model.WQ; ingo@1658: import de.intevation.flys.artifacts.resources.Resources; 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: ingo@1658: public static final String I18N_AT_HEADER = ingo@1658: "export.discharge.curve.at.header"; ingo@1658: 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: ingo@1658: protected static void printHeader( ingo@1658: PrintWriter out, ingo@1658: CallMeta callMeta, ingo@1658: String river, ingo@1658: double km ingo@1658: ) { ingo@1658: out.println(Resources.getMsg( ingo@1658: callMeta, ingo@1658: I18N_AT_HEADER, ingo@1658: I18N_AT_HEADER, ingo@1658: new Object[] { river, km } )); ingo@1658: } ingo@1658: ingo@1658: ingo@1658: public void write(Writer writer, CallMeta meta, String river, double km) ingo@1658: throws IOException ingo@1658: { sascha@729: PrintWriter out = new PrintWriter(writer); sascha@729: ingo@1658: // a header is required, because the desktop version of FLYS will skip ingo@1658: // the first row. ingo@1658: printHeader(out, meta, river, km); ingo@1658: 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@1662: double w = startW + i*0.01; sascha@1662: if (w < minW) { sascha@1662: out.print(EMPTY); sascha@1662: } sascha@1662: else { sascha@1662: printQ(out, getQ(w)); sascha@1662: } 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 :