Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QRangeTree.java @ 2230:59af81364eb1
Improved the 'historical discharge' calculation: implemented findValueForW().
flys-artifacts/trunk@3872 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Wed, 01 Feb 2012 15:41:11 +0000 |
parents | 9144e5a5027b |
children | ed550e325248 |
line wrap: on
line source
package de.intevation.flys.artifacts.model; import java.io.Serializable; import java.util.List; import org.apache.log4j.Logger; public class QRangeTree implements Serializable { private static Logger log = Logger.getLogger(QRangeTree.class); public static class Node implements Serializable { Node left; Node right; Node prev; Node next; double a; double b; double q; public Node() { } public Node(double a, double b, double q) { this.a = a; this.b = b; this.q = q; } protected final double interpolatePrev(double pos) { /* f(prev.b) = prev.q f(a) = q prev.q = m*prev.b + n q = m*a + n <=> n = q - m*a q - prev.q = m*(a - prev.b) m = (q - prev.q)/(a - prev.b) # a != prev.b */ if (a == prev.b) { return 0.5*(q + prev.q); } double m = (q - prev.q)/(a - prev.b); double n = q - m*a; return m*pos + n; } protected final double interpolateNext(double pos) { /* f(next.a) = next.q f(b) = q next.q = m*next.a + n q = m*b + n <=> n = q - m*b q - next.q = m*(b - next.a) m = (q - next.q)/(b - next.a) # b != next.a */ if (b == next.a) { return 0.5*(q + next.q); } double m = (q - next.q)/(b - next.a); double n = q - m*b; return m*pos + n; } public double findQ(double pos) { Node current = this; for (;;) { if (pos < current.a) { if (current.left != null) { current = current.left; continue; } return current.prev != null ? current.interpolatePrev(pos) : Double.NaN; } if (pos > current.b) { if (current.right != null) { current = current.right; continue; } return current.next != null ? current.interpolateNext(pos) : Double.NaN; } return current.q; } } } // class Node protected Node root; public QRangeTree() { } /** wstQRanges need to be sorted by range.a */ public QRangeTree(List<Object []> qRanges, int start, int stop) { if (stop <= start) { return; } Node [] nodes = new Node[stop-start]; for (int i = 0; i < nodes.length; ++i) { Object [] qRange = qRanges.get(start + i); Double q = (Double)qRange[1]; Double a = (Double)qRange[2]; Double b = (Double)qRange[3]; nodes[i] = new Node( a != null ? a.doubleValue() : -Double.MAX_VALUE, b != null ? b.doubleValue() : Double.MAX_VALUE, q.doubleValue()); } root = wireTree(nodes); } protected static Node wireTree(Node [] nodes) { for (int i = 0; i < nodes.length; ++i) { Node node = nodes[i]; if (i > 0 ) node.prev = nodes[i-1]; if (i < nodes.length-1) node.next = nodes[i+1]; } return buildTree(nodes, 0, nodes.length-1); } protected static Node buildTree(Node [] nodes, int lo, int hi) { if (lo > hi) { return null; } int mid = (lo + hi) >> 1; Node parent = nodes[mid]; parent.left = buildTree(nodes, lo, mid-1); parent.right = buildTree(nodes, mid+1, hi); return parent; } public double findQ(double pos) { return root != null ? root.findQ(pos) : Double.NaN; } private static final String name(Object o) { return String.valueOf(System.identityHashCode(o) & 0xffffffffL); } public String toGraph() { StringBuilder sb = new StringBuilder(); sb.append("subgraph c"); sb.append(name(this)); sb.append(" {\n"); if (root != null) { java.util.Deque<Node> stack = new java.util.ArrayDeque<Node>(); stack.push(root); while (!stack.isEmpty()) { Node current = stack.pop(); String name = "n" + name(current); sb.append(name); sb.append(" [label=\""); sb.append(current.a).append(", ").append(current.b); sb.append(": ").append(current.q).append("\"]\n"); if (current.left != null) { String leftName = name(current.left); sb.append(name).append(" -- n").append(leftName).append("\n"); stack.push(current.left); } if (current.right != null) { String rightName = name(current.right); sb.append(name).append(" -- n").append(rightName).append("\n"); stack.push(current.right); } } } sb.append("}\n"); return sb.toString(); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :