comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Lines.java @ 3818:dc18457b1cef

merged flys-artifacts/pre2.7-2012-03-16
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:59 +0200
parents a7def20539fb
children a6fa128e4654
comparison
equal deleted inserted replaced
2456:60ab1054069d 3818:dc18457b1cef
1 package de.intevation.flys.geom;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Iterator;
6
7 import java.awt.geom.Point2D;
8 import java.awt.geom.Line2D;
9
10 import de.intevation.flys.artifacts.math.Linear;
11
12 import org.apache.log4j.Logger;
13
14 import gnu.trove.TDoubleArrayList;
15
16 public class Lines
17 {
18 private static Logger log = Logger.getLogger(Lines.class);
19
20 public static final double EPSILON = 1e-4;
21
22 public static enum Mode { UNDEF, WET, DRY };
23
24 protected Lines() {
25 }
26
27 public static List<Line2D> fillWater(List<Point2D> points, double waterLevel) {
28
29 boolean debug = log.isDebugEnabled();
30
31 if (debug) {
32 log.debug("fillWater");
33 log.debug("----------------------------");
34 }
35
36 List<Line2D> result = new ArrayList();
37
38 int N = points.size();
39
40 if (N == 0) {
41 return result;
42 }
43
44 if (N == 1) {
45 Point2D p = points.get(0);
46 // Only generate point if over water
47 if (waterLevel > p.getY()) {
48 result.add(new Line2D.Double(
49 p.getX(), waterLevel,
50 p.getX(), waterLevel));
51 }
52 return result;
53 }
54
55 double minX = Double.MAX_VALUE;
56 double minY = Double.MAX_VALUE;
57 double maxX = -Double.MAX_VALUE;
58 double maxY = -Double.MAX_VALUE;
59
60 // To ensure for sequences of equals x's that
61 // the original index order is preserved.
62 for (Point2D p: points) {
63 double x = p.getX(), y = p.getY();
64 if (x < minX) minX = x;
65 if (x > maxX) maxX = x;
66 if (y < minY) minY = y;
67 if (y > maxY) maxY = y;
68 }
69
70 if (minY > waterLevel) { // profile completely over water level
71 log.debug("complete over water");
72 return result;
73 }
74
75 if (waterLevel > maxY) { // water floods profile
76 log.debug("complete under water");
77 result.add(new Line2D.Double(minX, waterLevel, maxX, waterLevel));
78 return result;
79 }
80
81 Mode mode = Mode.UNDEF;
82
83 double startX = minX;
84
85 for (int i = 1; i < N; ++i) {
86 Point2D p1 = points.get(i-1);
87 Point2D p2 = points.get(i);
88
89 if (p1.getY() < waterLevel && p2.getY() < waterLevel) {
90 // completely under water
91 if (debug) {
92 log.debug("under water: " + p1 + " " + p2);
93 }
94 if (mode != Mode.WET) {
95 startX = p1.getX();
96 mode = Mode.WET;
97 }
98 continue;
99 }
100
101 if (p1.getY() > waterLevel && p2.getY() > waterLevel) {
102 if (debug) {
103 log.debug("over water: " + p1 + " " + p2);
104 }
105 // completely over water
106 if (mode == Mode.WET) {
107 log.debug("over/wet");
108 result.add(new Line2D.Double(
109 startX, waterLevel,
110 p1.getX(), waterLevel));
111 }
112 mode = Mode.DRY;
113 continue;
114 }
115
116 if (Math.abs(p1.getX() - p2.getX()) < EPSILON) {
117 // vertical line
118 switch (mode) {
119 case WET:
120 log.debug("vertical/wet");
121 mode = Mode.DRY;
122 result.add(new Line2D.Double(
123 startX, waterLevel,
124 p1.getX(), waterLevel));
125 break;
126 case DRY:
127 log.debug("vertical/dry");
128 mode = Mode.WET;
129 startX = p2.getX();
130 break;
131 default: // UNDEF
132 log.debug("vertical/undef");
133 if (p2.getY() < waterLevel) {
134 mode = Mode.WET;
135 startX = p2.getX();
136 }
137 else {
138 mode = Mode.DRY;
139 }
140 }
141 continue;
142 }
143
144 // check if waterlevel directly hits the vertices;
145
146 boolean p1W = Math.abs(waterLevel - p1.getY()) < EPSILON;
147 boolean p2W = Math.abs(waterLevel - p2.getY()) < EPSILON;
148
149 if (p1W || p2W) {
150 if (debug) {
151 log.debug("water hits vertex: " + p1 + " " + p2 + " " + mode);
152 }
153 if (p1W && p2W) { // parallel to water -> dry
154 log.debug("water hits both vertices");
155 if (mode == Mode.WET) {
156 result.add(new Line2D.Double(
157 startX, waterLevel,
158 p1.getX(), waterLevel));
159 }
160 mode = Mode.DRY;
161 }
162 else if (p1W) { // p1 == waterlevel
163 log.debug("water hits first vertex");
164 if (p2.getY() > waterLevel) { // --> dry
165 if (mode == Mode.WET) {
166 result.add(new Line2D.Double(
167 startX, waterLevel,
168 p1.getX(), waterLevel));
169 }
170 mode = Mode.DRY;
171 }
172 else { // --> wet
173 if (mode != Mode.WET) {
174 startX = p1.getX();
175 mode = Mode.WET;
176 }
177 }
178 }
179 else { // p2 == waterlevel
180 log.debug("water hits second vertex");
181 if (p1.getY() > waterLevel) { // --> wet
182 if (mode != Mode.WET) {
183 startX = p2.getX();
184 mode = Mode.WET;
185 }
186 }
187 else { // --> dry
188 if (mode == Mode.WET) {
189 result.add(new Line2D.Double(
190 startX, waterLevel,
191 p2.getX(), waterLevel));
192 }
193 mode = Mode.DRY;
194 }
195 }
196 if (debug) {
197 log.debug("mode is now: " + mode);
198 }
199 continue;
200 }
201
202 // intersection case
203 double x = Linear.linear(
204 waterLevel,
205 p1.getY(), p2.getY(),
206 p1.getX(), p2.getX());
207
208 if (debug) {
209 log.debug("intersection p1:" + p1);
210 log.debug("intersection p2:" + p2);
211 log.debug("intersection at x: " + x);
212 }
213
214 switch (mode) {
215 case WET:
216 log.debug("intersect/wet");
217 mode = Mode.DRY;
218 result.add(new Line2D.Double(
219 startX, waterLevel,
220 x, waterLevel));
221 break;
222
223 case DRY:
224 log.debug("intersect/dry");
225 mode = Mode.WET;
226 startX = x;
227 break;
228
229 default: // UNDEF
230 log.debug("intersect/undef");
231 if (p2.getY() > waterLevel) {
232 log.debug("intersect/undef/over");
233 mode = Mode.DRY;
234 result.add(new Line2D.Double(
235 p1.getX(), waterLevel,
236 x, waterLevel));
237 }
238 else {
239 mode = Mode.WET;
240 startX = x;
241 }
242 } // switch mode
243 } // for all points p[i] and p[i-1]
244
245 if (mode == Mode.WET) {
246 result.add(new Line2D.Double(
247 startX, waterLevel,
248 maxX, waterLevel));
249 }
250
251 return result;
252 }
253
254 public static double [][] createWaterLines(
255 List<Point2D> points,
256 double waterlevel
257 ) {
258 List<Line2D> lines = fillWater(points, waterlevel);
259
260 TDoubleArrayList lxs = new TDoubleArrayList();
261 TDoubleArrayList lys = new TDoubleArrayList();
262
263 for (Iterator<Line2D> iter = lines.iterator(); iter.hasNext();) {
264 Line2D l = iter.next();
265 Point2D p1 = l.getP1();
266 Point2D p2 = l.getP2();
267 lxs.add(p1.getX());
268 lys.add(p1.getY());
269 lxs.add(p2.getX());
270 lys.add(p2.getY());
271 if (iter.hasNext()) {
272 lxs.add(Double.NaN);
273 lys.add(Double.NaN);
274 }
275 }
276
277 return new double [][] { lxs.toNativeArray(), lys.toNativeArray() };
278 }
279 }
280 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org