Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/exports/ATWriter.java @ 7165:6e42f0ff0329
Add ShearStress Processor
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Thu, 26 Sep 2013 12:21:11 +0200 |
parents | 3ac657d60e60 |
children | f51c943c707a |
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde * Software engineering by Intevation GmbH * * This file is Free Software under the GNU AGPL (>=v3) * and comes with ABSOLUTELY NO WARRANTY! Check out the * documentation coming with Dive4Elements River for details. */ package org.dive4elements.river.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 org.dive4elements.artifacts.CallMeta; import org.dive4elements.river.artifacts.model.WQ; import org.dive4elements.river.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 I18N_AT_CALC_GAUGE_HEADER = "export.discharge.curve.at.gauge.calc.header"; public static final String EMPTY = " "; public static double getQ(int w, UnivariateRealFunction qFunc) { try { double val = qFunc.value(w); return val; } catch (FunctionEvaluationException aode) { // should not happen logger.error("spline interpolation failed", aode); return Double.NaN; } } 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 printCalculatedGaugeHeader( PrintWriter out, CallMeta callMeta, String river, double km, String gName, BigDecimal datum, Date date, String unit ) { out.print("*" + Resources.getMsg( callMeta, I18N_AT_CALC_GAUGE_HEADER, I18N_AT_CALC_GAUGE_HEADER, new Object[] { river, gName, datum, unit } )); out.print("\r\n"); } protected static void printGaugeHeader( PrintWriter out, CallMeta callMeta, String river, double km, String gName, BigDecimal datum, Date date, String unit ) { DateFormat f = DateFormat.getDateInstance(DateFormat.MEDIUM, Resources.getLocale(callMeta)); out.print("*" + Resources.getMsg( callMeta, I18N_AT_GAUGE_HEADER, I18N_AT_GAUGE_HEADER, new Object[] { river, gName, f.format(date), datum, unit} )); 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 static void write( WQ values, Writer writer, CallMeta meta, String river, double km, String gName, BigDecimal datum, Date date, String unit) throws IOException { int minW; int maxW; double minQ; double maxQ; UnivariateRealFunction qFunc; WQ wq = WQ.getFixedWQforExportAtGauge(values, datum); // If we converted to centimeter we know that the WQ table is // calculated because of the assumption that all calculations // are in Meter and only the discharge tables data is in meter. boolean isCalculation = wq.getReferenceSystem() != values.getReferenceSystem(); int [] bounds = wq.longestIncreasingWRangeIndices(); if (logger.isDebugEnabled()) { logger.debug("exporting " + (isCalculation ? "calculated " : "") + "w between indices " + bounds[0] + " and " + bounds[1] + " (" + (int)Math.ceil(wq.getW(bounds[0])) + ", " + (int)Math.floor(wq.getW(bounds[1]))+ ")"); } if (bounds[1]-bounds[0] < 1) { // Only first w can be written out. minW = maxW = (int)Math.round(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 = (int)Math.ceil(wq.getW(bounds[0])); maxW = (int)Math.floor(wq.getW(bounds[1])); minQ = wq.getQ(bounds[0]); maxQ = wq.getQ(bounds[1]); PrintWriter out = new PrintWriter(writer); // A header is required, because the desktop version of FLYS will skip // the first row. if (gName != null) { if (isCalculation) { printCalculatedGaugeHeader(out, meta, river, km, gName, datum, date, unit); } else { printGaugeHeader(out, meta, river, km, gName, datum, date, unit); } } else { printHeader(out, meta, river, km); } int rest = minW % 10; int startW = minW - rest; if (logger.isDebugEnabled()) { logger.debug("startW: " + startW); logger.debug("rest: " + rest); logger.debug("maxW: " + maxW); } int col = 0; for (int w = startW; w < maxW; w++) { if (col == 0) { out.printf(Locale.US, "%8d", w); } if (w < minW) { out.print(EMPTY); } else { double actQ = getQ(w, qFunc); if (Double.isNaN(actQ)) { // Can't happen™ break; } else { printQ(out, actQ); } } 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 :