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