comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Lines.java @ 938:bd3683453928

Debugged the water fill algorithm. flys-artifacts/trunk@2330 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 14 Jul 2011 14:11:29 +0000
parents d0f3fea20f01
children a7def20539fb
comparison
equal deleted inserted replaced
937:9e813e9137a5 938:bd3683453928
1 package de.intevation.flys.geom.Lines; 1 package de.intevation.flys.geom;
2 2
3 import java.util.List; 3 import java.util.List;
4 import java.util.ArrayList; 4 import java.util.ArrayList;
5 import java.util.Arrays;
6 5
7 import java.awt.geom.Point2D; 6 import java.awt.geom.Point2D;
8 import java.awt.geom.Line2D; 7 import java.awt.geom.Line2D;
9 8
10 import de.intevation.flys.artifacts.math.Linear; 9 import de.intevation.flys.artifacts.math.Linear;
11 10
11 import org.apache.log4j.Logger;
12
12 public class Lines 13 public class Lines
13 { 14 {
15 private static Logger log = Logger.getLogger(Lines.class);
16
14 public static final double EPSILON = 1e-4; 17 public static final double EPSILON = 1e-4;
15 18
16 public static enum Mode { UNDEF, WET, DRY }; 19 public static enum Mode { UNDEF, WET, DRY };
17 20
18 protected Lines() { 21 protected Lines() {
19 } 22 }
20 23
21 public static final class StableIndex
22 implements Comparable<StableIndex>
23 {
24 protected Point2D point;
25 protected int index;
26
27 public StableIndex(Point2D point, int index) {
28 this.point = point;
29 this.index = index;
30 }
31
32 public int compareTo(StableIndex other) {
33 double diff = point.getX() - other.point.getX();
34 if (diff < -EPSILON ) return -1;
35 if (diff > +EPSILON ) return +1;
36 if (index < other.index) return -1;
37 if (index > other.index) return +1;
38 return 0;
39 }
40 } // class StableIndex
41
42 public static List<Line2D> fillWater(List<Point2D> points, double waterLevel) { 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 }
43 32
44 List<Line2D> result = new ArrayList(); 33 List<Line2D> result = new ArrayList();
45 34
46 int N = points.size(); 35 int N = points.size();
47 36
65 double maxX = -Double.MAX_VALUE; 54 double maxX = -Double.MAX_VALUE;
66 double maxY = -Double.MAX_VALUE; 55 double maxY = -Double.MAX_VALUE;
67 56
68 // To ensure for sequences of equals x's that 57 // To ensure for sequences of equals x's that
69 // the original index order is preserved. 58 // the original index order is preserved.
70 StableIndex [] ps = new StableIndex[N]; 59 for (Point2D p: points) {
71 for (int i = 0; i < N; ++i) {
72 Point2D p = points.get(i);
73 ps[i] = new StableIndex(p, i);
74 double x = p.getX(), y = p.getY(); 60 double x = p.getX(), y = p.getY();
75 if (x < minX) minX = x; 61 if (x < minX) minX = x;
76 if (x > maxX) maxX = x; 62 if (x > maxX) maxX = x;
77 if (y < minY) minY = y; 63 if (y < minY) minY = y;
78 if (y > maxY) maxY = y; 64 if (y > maxY) maxY = y;
79 } 65 }
80 66
81 if (minY > waterLevel) { // profile completely over water level 67 if (minY > waterLevel) { // profile completely over water level
68 log.debug("complete over water");
82 return result; 69 return result;
83 } 70 }
84 71
85 if (waterLevel > maxY) { // water floods profile 72 if (waterLevel > maxY) { // water floods profile
73 log.debug("complete under water");
86 result.add(new Line2D.Double(minX, waterLevel, maxX, waterLevel)); 74 result.add(new Line2D.Double(minX, waterLevel, maxX, waterLevel));
87 return result; 75 return result;
88 } 76 }
89 77
90 Arrays.sort(ps);
91
92 Mode mode = Mode.UNDEF; 78 Mode mode = Mode.UNDEF;
93 79
94 double startX = minX; 80 double startX = minX;
95 81
96 for (int i = 1; i < N; ++i) { 82 for (int i = 1; i < N; ++i) {
97 Point2D p1 = ps[i-1].point; 83 Point2D p1 = points.get(i-1);
98 Point2D p2 = ps[i ].point; 84 Point2D p2 = points.get(i);
99 85
100 if (p1.getX() < waterLevel && p2.getX() < waterLevel) { 86 if (p1.getY() < waterLevel && p2.getY() < waterLevel) {
101 // completely under water 87 // completely under water
102 continue; 88 if (debug) {
103 } 89 log.debug("under water: " + p1 + " " + p2);
104 90 }
105 if (p1.getX() > waterLevel && p2.getX() > waterLevel) { 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 }
106 // completely over water 102 // completely over water
107 if (mode == Mode.WET) { 103 if (mode == Mode.WET) {
104 log.debug("over/wet");
108 result.add(new Line2D.Double( 105 result.add(new Line2D.Double(
109 startX, waterLevel, 106 startX, waterLevel,
110 p1.getX(), waterLevel)); 107 p1.getX(), waterLevel));
111 } 108 }
112 mode = Mode.DRY; 109 mode = Mode.DRY;
115 112
116 if (Math.abs(p1.getX() - p2.getX()) < EPSILON) { 113 if (Math.abs(p1.getX() - p2.getX()) < EPSILON) {
117 // vertical line 114 // vertical line
118 switch (mode) { 115 switch (mode) {
119 case WET: 116 case WET:
117 log.debug("vertical/wet");
120 mode = Mode.DRY; 118 mode = Mode.DRY;
121 result.add(new Line2D.Double( 119 result.add(new Line2D.Double(
122 startX, waterLevel, 120 startX, waterLevel,
123 p1.getX(), waterLevel)); 121 p1.getX(), waterLevel));
124 break; 122 break;
125 case DRY: 123 case DRY:
124 log.debug("vertical/dry");
126 mode = Mode.WET; 125 mode = Mode.WET;
127 startX = p2.getX(); 126 startX = p2.getX();
128 break; 127 break;
129 default: // UNDEF 128 default: // UNDEF
129 log.debug("vertical/undef");
130 if (p2.getY() < waterLevel) { 130 if (p2.getY() < waterLevel) {
131 mode = Mode.WET; 131 mode = Mode.WET;
132 startX = p2.getX(); 132 startX = p2.getX();
133 } 133 }
134 else { 134 else {
136 } 136 }
137 } 137 }
138 continue; 138 continue;
139 } 139 }
140 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
141 // intersection case 199 // intersection case
142 double x = Linear.linear( 200 double x = Linear.linear(
143 waterLevel, 201 waterLevel,
144 p1.getY(), p1.getX(), 202 p1.getY(), p2.getY(),
145 p2.getY(), p2.getX()); 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 }
146 210
147 switch (mode) { 211 switch (mode) {
148 case WET: 212 case WET:
213 log.debug("intersect/wet");
149 mode = Mode.DRY; 214 mode = Mode.DRY;
150 result.add(new Line2D.Double( 215 result.add(new Line2D.Double(
151 startX, waterLevel, 216 startX, waterLevel,
152 x, waterLevel)); 217 x, waterLevel));
153 break; 218 break;
154 219
155 case DRY: 220 case DRY:
221 log.debug("intersect/dry");
156 mode = Mode.WET; 222 mode = Mode.WET;
157 startX = x; 223 startX = x;
158 break; 224 break;
159 225
160 default: // UNDEF 226 default: // UNDEF
227 log.debug("intersect/undef");
161 if (p2.getY() > waterLevel) { 228 if (p2.getY() > waterLevel) {
229 log.debug("intersect/undef/over");
162 mode = Mode.DRY; 230 mode = Mode.DRY;
163 result.add(new Line2D.Double( 231 result.add(new Line2D.Double(
164 p1.getX(), waterLevel, 232 p1.getX(), waterLevel,
165 x, waterLevel)); 233 x, waterLevel));
166 } 234 }

http://dive4elements.wald.intevation.org