diff artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation4.java @ 5838:5aa05a7a34b7

Rename modules to more fitting names.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 15:23:37 +0200
parents flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation4.java@bd047b71ab37
children 4897a58c8746
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation4.java	Thu Apr 25 15:23:37 2013 +0200
@@ -0,0 +1,370 @@
+package org.dive4elements.river.artifacts.model;
+
+import org.dive4elements.river.artifacts.access.Calculation4Access;
+
+import org.dive4elements.river.artifacts.math.BackJumpCorrector;
+import org.dive4elements.river.artifacts.math.Function;
+import org.dive4elements.river.artifacts.math.Identity;
+import org.dive4elements.river.artifacts.math.Linear;
+
+import org.dive4elements.river.artifacts.model.RiverFactory;
+
+import org.dive4elements.river.artifacts.model.WstValueTable.QPosition;
+
+import org.dive4elements.river.model.River;
+
+import org.dive4elements.river.utils.DoubleUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+public class Calculation4
+extends      Calculation
+{
+    private static Logger logger = Logger.getLogger(Calculation4.class);
+
+    public static final double MINIMAL_STEP_WIDTH = 1e-5;
+
+    protected List<Segment> segments;
+
+    protected boolean isQ;
+    protected double  from;
+    protected double  to;
+    protected double  step;
+    protected String  river;
+
+    public Calculation4() {
+    }
+
+    public Calculation4(Calculation4Access access) {
+        logger.debug("Calculation4Access.cnst");
+        String        river    = access.getRiver();
+        List<Segment> segments = access.getSegments();
+        double []     range    = access.getFromToStep();
+        boolean       isQ      = access.isQ();
+
+        if (river == null) {
+            addProblem("no.river.selected");
+        }
+
+        if (range == null) {
+            addProblem("no.range.found");
+        }
+
+        if (segments == null || segments.isEmpty()) {
+            addProblem("cannot.create.segments");
+        }
+
+        if (!hasProblems()) {
+            this.river    = river;
+            this.segments = segments;
+            this.from     = range[0];
+            this.to       = range[1];
+            this.step     = range[2];
+            this.isQ      = isQ;
+        }
+    }
+
+    public CalculationResult calculate() {
+        if (hasProblems()) {
+            return new CalculationResult(new WQKms[0], this);
+        }
+
+        WstValueTable table = null;
+        River r = RiverFactory.getRiver(river);
+        if (r == null) {
+            addProblem("no.river.found");
+        }
+        else {
+            table = WstValueTableFactory.getTable(r);
+            if (table == null) {
+                addProblem("no.wst.for.river");
+            }
+            else {
+                Segment.setReferencePointConvertQ(segments, r, isQ, this);
+            }
+        }
+
+        return hasProblems()
+            ? new CalculationResult(new WQKms[0], this)
+            : innerCalculate(table);
+    }
+
+    protected CalculationResult innerCalculate(WstValueTable table) {
+        boolean debug = logger.isDebugEnabled();
+
+        if (debug) {
+            logger.debug(
+                "calculate from " + from + " to " + to + " step " + step);
+            logger.debug("# segments: " + segments.size());
+            for (Segment segment: segments) {
+                logger.debug("  " + segment);
+            }
+        }
+
+        int numResults = segments.get(0).values.length;
+
+        if (numResults < 1) {
+            logger.debug("no values given");
+            addProblem("no.values.given");
+            return new CalculationResult(new WQKms[0], this);
+        }
+
+
+        WQKms [] results = new WQKms[numResults];
+        for (int i = 0; i < results.length; ++i) {
+            results[i] = new WQKms();
+        }
+
+        if (Math.abs(step) < MINIMAL_STEP_WIDTH) {
+            step = MINIMAL_STEP_WIDTH;
+        }
+
+        if (from > to) {
+            step = -step;
+        }
+
+        QPosition [] qPositions = new QPosition[numResults];
+
+        Function [] functions = new Function[numResults];
+
+        double [] out = new double[2];
+
+        Segment sentinel = new Segment(Double.MAX_VALUE);
+        Segment s1 = sentinel, s2 = sentinel;
+
+        for (double pos = from;
+             from < to ? pos <= to : pos >= to;
+             pos = DoubleUtil.round(pos + step)
+        ) {
+            if (pos < s1.referencePoint || pos > s2.referencePoint) {
+                if (debug) {
+                    logger.debug("need to find new interval for " + pos);
+                }
+                // find new interval
+                if (pos <= segments.get(0).referencePoint) {
+                    // before first segment -> "gleichwertig"
+                    if (debug) {
+                        logger.debug("before first segment -> gleichwertig");
+                    }
+                    Segment   first  = segments.get(0);
+                    double [] values = first.values;
+                    double    refPos = first.referencePoint;
+                    for (int i = 0; i < qPositions.length; ++i) {
+                        qPositions[i] = table.getQPosition(
+                            refPos, values[i]);
+                    }
+                    sentinel.setReferencePoint(-Double.MAX_VALUE);
+                    s1 = sentinel;
+                    s2 = segments.get(0);
+                    Arrays.fill(functions, Identity.IDENTITY);
+                }
+                else if (pos >= segments.get(segments.size()-1).referencePoint) {
+                    // after last segment -> "gleichwertig"
+                    if (debug) {
+                        logger.debug("after last segment -> gleichwertig");
+                    }
+                    Segment   last   = segments.get(segments.size()-1);
+                    double [] values = last.values;
+                    double    refPos = last.referencePoint;
+                    for (int i = 0; i < qPositions.length; ++i) {
+                        qPositions[i] = table.getQPosition(
+                            refPos, values[i]);
+                    }
+                    sentinel.setReferencePoint(Double.MAX_VALUE);
+                    s1 = last;
+                    s2 = sentinel;
+                    Arrays.fill(functions, Identity.IDENTITY);
+                }
+                else { // "ungleichwertig"
+                    // find matching interval
+                    if (debug) {
+                        logger.debug("in segments -> ungleichwertig");
+                    }
+                    s1 = s2 = null;
+                    for (int i = 1, N = segments.size(); i < N; ++i) {
+                        Segment si1 = segments.get(i-1);
+                        Segment si  = segments.get(i);
+                        if (debug) {
+                            logger.debug("check " + pos + " in " +
+                                si1.referencePoint + " - " + si.referencePoint);
+                        }
+                        if (pos >= si1.referencePoint
+                        &&  pos <= si. referencePoint) {
+                            s1 = si1;
+                            s2 = si;
+                            break;
+                        }
+                    }
+
+                    if (s1 == null) {
+                        throw new IllegalStateException("no interval found");
+                    }
+
+                    Segment anchor, free;
+
+                    if (from > to) { anchor = s1; free = s2; }
+                    else           { anchor = s2; free = s1; }
+
+                    // build transforms based on "gleichwertiger" phase
+                    for (int i = 0; i < qPositions.length; ++i) {
+                        QPosition qi = table.getQPosition(
+                            anchor.referencePoint,
+                            anchor.values[i]);
+
+                        if ((qPositions[i] = qi) == null) {
+                            addProblem(pos, "cannot.find.q", anchor.values[i]);
+                            functions[i] = Identity.IDENTITY;
+                        }
+                        else {
+                            double qA = table.getQ(qi, anchor.referencePoint);
+                            double qF = table.getQ(qi, free  .referencePoint);
+
+                            functions[i] = Double.isNaN(qA) || Double.isNaN(qF)
+                                ? Identity.IDENTITY
+                                : new Linear(
+                                    qA, qF,
+                                    anchor.values[i], free.values[i]);
+
+                            if (debug) {
+                                logger.debug(
+                                    anchor.referencePoint + ": " +
+                                    qA + " -> " + functions[i].value(qA) +
+                                    " / " + free.referencePoint + ": " +
+                                    qF + " -> " + functions[i].value(qF));
+                            }
+                        }
+                    } // build transforms
+                } // "ungleichwertiges" interval
+            } // find matching interval
+
+            for (int i = 0; i < qPositions.length; ++i) {
+                QPosition qPosition = qPositions[i];
+
+                if (qPosition == null) {
+                    continue;
+                }
+
+                if (table.interpolate(pos, out, qPosition, functions[i])) {
+                    results[i].add(out[0], out[1], pos);
+                }
+                else {
+                    addProblem(pos, "cannot.interpolate.w.q");
+                }
+            }
+        }
+
+        // Backjump correction
+        for (int i = 0; i < results.length; ++i) {
+            BackJumpCorrector bjc = new BackJumpCorrector();
+
+            double [] ws  = results[i].getWs();
+            double [] kms = results[i].getKms();
+
+            if (bjc.doCorrection(kms, ws, this)) {
+                results[i] = new WQCKms(results[i], bjc.getCorrected());
+            }
+        }
+
+        // Name the curves.
+        for (int i = 0; i < results.length; ++i) {
+            results[i].setName(createName(i));
+        }
+
+        // Generate the "Umhuellende".
+        ConstantWQKms [] infoldings =
+            generateInfolding(table, results, from, to, step);
+
+        // TODO: Use qkms in a new result type.
+        WQKms [] newResults = new WQKms[results.length + infoldings.length];
+        System.arraycopy(
+            results, 0, newResults, 0, results.length);
+        System.arraycopy(
+            infoldings, 0, newResults, results.length, infoldings.length);
+
+        return new CalculationResult(newResults, this);
+    }
+
+    protected ConstantWQKms [] generateInfolding(
+        WstValueTable wst,
+        WQKms []      results,
+        double        from,
+        double        to,
+        double        step
+    ) {
+        WstValueTable.Column [] columns = wst.getColumns();
+
+        InfoldingColumns ic = new InfoldingColumns(columns);
+        ic.markInfoldingColumns(results);
+
+        List<ConstantWQKms> infoldings = new ArrayList<ConstantWQKms>();
+
+        boolean [] infoldingColumns = ic.getInfoldingColumns();
+
+        double [] kms = null;
+        double [] ws  = null;
+
+        for (int i = 0; i < infoldingColumns.length; ++i) {
+            if (!infoldingColumns[i]) {
+                continue;
+            }
+
+            if (kms == null) {
+                kms = DoubleUtil.explode(from, to, step);
+                ws  = new double[kms.length];
+            }
+
+            QRangeTree.QuickQFinder qf =
+                columns[i].getQRangeTree().new QuickQFinder();
+
+            int numProblemsBefore = numProblems();
+            double [] qs = qf.findQs(kms, this);
+
+            String name = columns[i].getName();
+            ConstantWQKms infolding = new ConstantWQKms(kms, qs, ws, name);
+
+            if (numProblems() > numProblemsBefore) {
+                infolding.removeNaNs();
+            }
+
+            infoldings.add(infolding);
+        }
+
+        for (int i = 0; i < infoldings.size(); i++) {
+            String name = infoldings.get(i).getName();
+            // TODO: i18n
+            if (i == 0) {
+                infoldings.get(i).setName("untere Umh\u00fcllende " + name);
+            }
+            else if (i ==  infoldings.size() - 1) {
+                infoldings.get(i).setName("obere Umh\u00fcllende " + name);
+            }
+            else {
+                infoldings.get(i).setName("geschnitten " + name);
+            }
+        }
+        return infoldings.toArray(new ConstantWQKms[infoldings.size()]);
+    }
+
+    // TODO: issue1109/2, merge with FixRealizingCalculation
+    protected String createName(int index) {
+        // TODO: i18n
+        StringBuilder sb = new StringBuilder(isQ ? "Q" : "W");
+        sb.append(" benutzerdefiniert (");
+        for (int i = 0, N = segments.size(); i < N; ++i) {
+            if (i > 0) {
+                sb.append("; ");
+            }
+            Segment segment = segments.get(i);
+            sb.append((segment.backup != null
+                ? segment.backup
+                : segment.values)[index]);
+        }
+        sb.append(')');
+        return sb.toString();
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org