comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/math/WKmsOperation.java @ 3318:dbe2f85bf160

merged flys-artifacts/2.8
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:35 +0200
parents 5642a83420f2
children
comparison
equal deleted inserted replaced
2987:98c7a46ec5ae 3318:dbe2f85bf160
1 package de.intevation.flys.artifacts.math;
2
3 import de.intevation.flys.artifacts.model.WKms;
4 import de.intevation.flys.artifacts.model.WKmsImpl;
5
6 import java.util.Arrays;
7
8 public abstract class WKmsOperation
9 {
10 public static final double EPSILON = 1e-6;
11
12 public static final class KmW
13 implements Comparable<KmW>
14 {
15 protected double km;
16 protected double w;
17
18 public KmW(double km, double w) {
19 this.km = km;
20 this.w = w;
21 }
22
23 public int compareTo(KmW other) {
24 return km < other.km
25 ? -1
26 : km > other.km ? +1 : 0;
27 }
28
29 public boolean kmEquals(KmW other) {
30 return Math.abs(km - other.km) < EPSILON;
31 }
32
33 public double subtract(KmW other) {
34 return w - other.w;
35 }
36 } // class KmW
37
38 public static final WKmsOperation SUBTRACTION = new WKmsOperation() {
39
40 @Override
41 public WKms operate(WKms a, WKms b) {
42 return subtract(a, b);
43 }
44 };
45
46 protected WKmsOperation() {
47 }
48
49 public abstract WKms operate(WKms a, WKms b);
50
51 /**
52 * Subtract two series from each other, interpolate values
53 * missing in one series in the other.
54 */
55 public static WKms subtract(WKms minuend, WKms subtrahend) {
56
57 int M = minuend .size();
58 int S = subtrahend.size();
59
60 // Don't subtract empty sets
61 if (M < 1 || S < 1) {
62 return new WKmsImpl();
63 }
64
65 KmW [] ms = new KmW[M];
66 KmW [] ss = new KmW[S];
67
68 for (int i = 0; i < M; ++i) {
69 ms[i] = new KmW(minuend.getKm(i), minuend.getW(i));
70 }
71
72 for (int i = 0; i < S; ++i) {
73 ss[i] = new KmW(subtrahend.getKm(i), subtrahend.getW(i));
74 }
75
76 Arrays.sort(ms);
77 Arrays.sort(ss);
78
79 // no overlap -> empty result set
80 if (ms[0].km > ss[S-1].km || ss[0].km > ms[M-1].km) {
81 return new WKmsImpl();
82 }
83
84 WKmsImpl result = new WKmsImpl();
85
86 int mi = 0;
87 int si = 0;
88
89 OUT: while (mi < M && si < S) {
90 KmW m = ms[mi];
91 KmW s = ss[si];
92
93 if (m.km + EPSILON < s.km) {
94 // minuend is before subtrahend
95
96 while (ms[mi].km + EPSILON < s.km) {
97 if (++mi >= M) {
98 break OUT;
99 }
100 }
101
102 if (ms[mi].km + EPSILON > s.km) {
103 double mw = Linear.linear(
104 s.km,
105 ms[mi-1].km, ms[mi].km,
106 ms[mi-1].w, ms[mi].w);
107 result.add(s.km, mw - s.w);
108 ++si;
109 }
110 else { // s.km == ms[mi].km
111 result.add(s.km, ms[mi].subtract(s));
112 ++mi;
113 ++si;
114 }
115 }
116 else if (m.km > s.km + EPSILON) {
117 // subtrahend is before minuend
118
119 while (m.km > ss[si].km + EPSILON) {
120 if (++si >= S) {
121 break OUT;
122 }
123 }
124
125 if (ss[si].km + EPSILON > m.km) {
126 double sw = Linear.linear(
127 m.km,
128 ss[si-1].km, ss[si].km,
129 ss[si-1].w, ss[si].w);
130 result.add(m.km, m.w - sw);
131 }
132 else { // ss[si].km == m.km
133 result.add(m.km, m.subtract(ss[si]));
134 ++mi;
135 ++si;
136 }
137 }
138 else { // m.km == s.km
139 result.add(s.km, m.subtract(s));
140 ++mi;
141 ++si;
142 }
143 }
144
145 return result;
146 }
147 }
148 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org