Mercurial > dive4elements > river
diff 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 |
line wrap: on
line diff
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Lines.java Thu Jul 14 11:27:01 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Lines.java Thu Jul 14 14:11:29 2011 +0000 @@ -1,16 +1,19 @@ -package de.intevation.flys.geom.Lines; +package de.intevation.flys.geom; import java.util.List; import java.util.ArrayList; -import java.util.Arrays; import java.awt.geom.Point2D; import java.awt.geom.Line2D; import de.intevation.flys.artifacts.math.Linear; +import org.apache.log4j.Logger; + public class Lines { + private static Logger log = Logger.getLogger(Lines.class); + public static final double EPSILON = 1e-4; public static enum Mode { UNDEF, WET, DRY }; @@ -18,28 +21,14 @@ protected Lines() { } - public static final class StableIndex - implements Comparable<StableIndex> - { - protected Point2D point; - protected int index; - - public StableIndex(Point2D point, int index) { - this.point = point; - this.index = index; - } + public static List<Line2D> fillWater(List<Point2D> points, double waterLevel) { - public int compareTo(StableIndex other) { - double diff = point.getX() - other.point.getX(); - if (diff < -EPSILON ) return -1; - if (diff > +EPSILON ) return +1; - if (index < other.index) return -1; - if (index > other.index) return +1; - return 0; + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("fillWater"); + log.debug("----------------------------"); } - } // class StableIndex - - public static List<Line2D> fillWater(List<Point2D> points, double waterLevel) { List<Line2D> result = new ArrayList(); @@ -67,10 +56,7 @@ // To ensure for sequences of equals x's that // the original index order is preserved. - StableIndex [] ps = new StableIndex[N]; - for (int i = 0; i < N; ++i) { - Point2D p = points.get(i); - ps[i] = new StableIndex(p, i); + for (Point2D p: points) { double x = p.getX(), y = p.getY(); if (x < minX) minX = x; if (x > maxX) maxX = x; @@ -79,32 +65,43 @@ } if (minY > waterLevel) { // profile completely over water level + log.debug("complete over water"); return result; } if (waterLevel > maxY) { // water floods profile + log.debug("complete under water"); result.add(new Line2D.Double(minX, waterLevel, maxX, waterLevel)); return result; } - Arrays.sort(ps); - Mode mode = Mode.UNDEF; - double startX = minX; + double startX = minX; for (int i = 1; i < N; ++i) { - Point2D p1 = ps[i-1].point; - Point2D p2 = ps[i ].point; + Point2D p1 = points.get(i-1); + Point2D p2 = points.get(i); - if (p1.getX() < waterLevel && p2.getX() < waterLevel) { + if (p1.getY() < waterLevel && p2.getY() < waterLevel) { // completely under water + if (debug) { + log.debug("under water: " + p1 + " " + p2); + } + if (mode != Mode.WET) { + startX = p1.getX(); + mode = Mode.WET; + } continue; } - if (p1.getX() > waterLevel && p2.getX() > waterLevel) { + if (p1.getY() > waterLevel && p2.getY() > waterLevel) { + if (debug) { + log.debug("over water: " + p1 + " " + p2); + } // completely over water if (mode == Mode.WET) { + log.debug("over/wet"); result.add(new Line2D.Double( startX, waterLevel, p1.getX(), waterLevel)); @@ -117,16 +114,19 @@ // vertical line switch (mode) { case WET: + log.debug("vertical/wet"); mode = Mode.DRY; result.add(new Line2D.Double( startX, waterLevel, p1.getX(), waterLevel)); break; case DRY: + log.debug("vertical/dry"); mode = Mode.WET; startX = p2.getX(); break; default: // UNDEF + log.debug("vertical/undef"); if (p2.getY() < waterLevel) { mode = Mode.WET; startX = p2.getX(); @@ -138,14 +138,79 @@ continue; } + // check if waterlevel directly hits the vertices; + + boolean p1W = Math.abs(waterLevel - p1.getY()) < EPSILON; + boolean p2W = Math.abs(waterLevel - p2.getY()) < EPSILON; + + if (p1W || p2W) { + if (debug) { + log.debug("water hits vertex: " + p1 + " " + p2 + " " + mode); + } + if (p1W && p2W) { // parallel to water -> dry + log.debug("water hits both vertices"); + if (mode == Mode.WET) { + result.add(new Line2D.Double( + startX, waterLevel, + p1.getX(), waterLevel)); + } + mode = Mode.DRY; + } + else if (p1W) { // p1 == waterlevel + log.debug("water hits first vertex"); + if (p2.getY() > waterLevel) { // --> dry + if (mode == Mode.WET) { + result.add(new Line2D.Double( + startX, waterLevel, + p1.getX(), waterLevel)); + } + mode = Mode.DRY; + } + else { // --> wet + if (mode != Mode.WET) { + startX = p1.getX(); + mode = Mode.WET; + } + } + } + else { // p2 == waterlevel + log.debug("water hits second vertex"); + if (p1.getY() > waterLevel) { // --> wet + if (mode != Mode.WET) { + startX = p2.getX(); + mode = Mode.WET; + } + } + else { // --> dry + if (mode == Mode.WET) { + result.add(new Line2D.Double( + startX, waterLevel, + p2.getX(), waterLevel)); + } + mode = Mode.DRY; + } + } + if (debug) { + log.debug("mode is now: " + mode); + } + continue; + } + // intersection case double x = Linear.linear( waterLevel, - p1.getY(), p1.getX(), - p2.getY(), p2.getX()); + p1.getY(), p2.getY(), + p1.getX(), p2.getX()); + + if (debug) { + log.debug("intersection p1:" + p1); + log.debug("intersection p2:" + p2); + log.debug("intersection at x: " + x); + } switch (mode) { case WET: + log.debug("intersect/wet"); mode = Mode.DRY; result.add(new Line2D.Double( startX, waterLevel, @@ -153,12 +218,15 @@ break; case DRY: + log.debug("intersect/dry"); mode = Mode.WET; startX = x; break; default: // UNDEF + log.debug("intersect/undef"); if (p2.getY() > waterLevel) { + log.debug("intersect/undef/over"); mode = Mode.DRY; result.add(new Line2D.Double( p1.getX(), waterLevel,