Mercurial > dive4elements > river
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 : |