Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Lines.java @ 2089:0da8874bd378
Added initial state to map artifact to be able to advance and step back.
The map artifact overrides describe() to have the complete UI information in the
describe response document.
flys-artifacts/trunk@3613 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Raimund Renkert <raimund.renkert@intevation.de> |
---|---|
date | Fri, 06 Jan 2012 12:02:10 +0000 |
parents | a7def20539fb |
children | a6fa128e4654 |
line wrap: on
line source
package de.intevation.flys.geom; import java.util.ArrayList; import java.util.List; import java.util.Iterator; import java.awt.geom.Point2D; import java.awt.geom.Line2D; import de.intevation.flys.artifacts.math.Linear; import org.apache.log4j.Logger; import gnu.trove.TDoubleArrayList; 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 }; protected Lines() { } public static List<Line2D> fillWater(List<Point2D> points, double waterLevel) { boolean debug = log.isDebugEnabled(); if (debug) { log.debug("fillWater"); log.debug("----------------------------"); } List<Line2D> result = new ArrayList(); int N = points.size(); if (N == 0) { return result; } if (N == 1) { Point2D p = points.get(0); // Only generate point if over water if (waterLevel > p.getY()) { result.add(new Line2D.Double( p.getX(), waterLevel, p.getX(), waterLevel)); } return result; } double minX = Double.MAX_VALUE; double minY = Double.MAX_VALUE; double maxX = -Double.MAX_VALUE; double maxY = -Double.MAX_VALUE; // To ensure for sequences of equals x's that // the original index order is preserved. for (Point2D p: points) { double x = p.getX(), y = p.getY(); if (x < minX) minX = x; if (x > maxX) maxX = x; if (y < minY) minY = y; if (y > maxY) maxY = y; } 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; } Mode mode = Mode.UNDEF; double startX = minX; for (int i = 1; i < N; ++i) { Point2D p1 = points.get(i-1); Point2D p2 = points.get(i); 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.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)); } mode = Mode.DRY; continue; } if (Math.abs(p1.getX() - p2.getX()) < EPSILON) { // 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(); } else { mode = Mode.DRY; } } 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(), 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, x, waterLevel)); 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, x, waterLevel)); } else { mode = Mode.WET; startX = x; } } // switch mode } // for all points p[i] and p[i-1] if (mode == Mode.WET) { result.add(new Line2D.Double( startX, waterLevel, maxX, waterLevel)); } return result; } public static double [][] createWaterLines( List<Point2D> points, double waterlevel ) { List<Line2D> lines = fillWater(points, waterlevel); TDoubleArrayList lxs = new TDoubleArrayList(); TDoubleArrayList lys = new TDoubleArrayList(); for (Iterator<Line2D> iter = lines.iterator(); iter.hasNext();) { Line2D l = iter.next(); Point2D p1 = l.getP1(); Point2D p2 = l.getP2(); lxs.add(p1.getX()); lys.add(p1.getY()); lxs.add(p2.getX()); lys.add(p2.getY()); if (iter.hasNext()) { lxs.add(Double.NaN); lys.add(Double.NaN); } } return new double [][] { lxs.toNativeArray(), lys.toNativeArray() }; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :