Mercurial > dive4elements > gnv-client
diff gnv-artifacts/src/main/java/de/intevation/gnv/math/Point2d.java @ 1119:7c4f81f74c47
merged gnv-artifacts
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:00 +0200 |
parents | f953c9a559d8 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/Point2d.java Fri Sep 28 12:14:00 2012 +0200 @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2010 by Intevation GmbH + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + */ + +package de.intevation.gnv.math; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Envelope; + +import java.util.Comparator; + +import org.apache.log4j.Logger; + +/** + * Point which besides the x, y, z coodinates has an index i, j pair + * to model neighborhood. + * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> + */ +public class Point2d +extends Coordinate +{ + private static Logger log = Logger.getLogger(Point2d.class); + + /** + * Numerical tolerance epsilon: {@value} + */ + public static final double EPSILON = 1e-3d; + + /** + * Compares two Point2ds by their x coordinates + */ + public static final Comparator X_COMPARATOR = new Comparator() { + public int compare(Object a, Object b) { + double xa = ((Coordinate)a).x; + double xb = ((Coordinate)b).x; + if (xa < xb) return -1; + if (xa > xb) return +1; + return 0; + } + }; + + /** + * Compares two Point2ds by their y coordinates. + */ + public static final Comparator Y_COMPARATOR = new Comparator() { + public int compare(Object a, Object b) { + double ya = ((Coordinate)a).y; + double yb = ((Coordinate)b).y; + if (ya < yb) return -1; + if (ya > yb) return +1; + return 0; + } + }; + + /** + * The i index of this Point2d. + */ + public int i; + /** + * The j index of this Point2d. + */ + public int j; + + /** + * Default constructor. + */ + public Point2d() { + } + + /** + * Constructor setting x and y coordinate. + * @param x The x coordinate. + * @param y The y coordinate. + */ + public Point2d(double x, double y) { + super(x, y); + } + + /** + * Constructor setting x, y and i, j. + * @param x The x coordinate. + * @param y The y coordinate. + * @param i The i index. + * @param j The j index. + */ + public Point2d(double x, double y, int i, int j) { + super(x, y); + this.i = i; + this.j = j; + } + + /** + * Constructor setting x, y, z and i, j. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @param i The i index. + * @param j The j index. + */ + public Point2d(double x, double y, double z, int i, int j) { + super(x, y, z); + this.i = i; + this.j = j; + } + + /** + * Calculates the L1 distance to another Point2d. + * @param other The other Point2d. + * @return The L1 distance. + */ + public double L1(Point2d other) { + return L1Comparator.L1(this, other); + } + + /** + * Creates an envelope around this Point2d with + * the numerical tolerance of {@link #EPSILON}. + * @return The envelope. + */ + public Envelope envelope() { + return envelope(EPSILON); + } + + /** + *Creates an envelope around this Point2d with + * a given tolerance. + * @param epsilon The tolerance in all directions. + * @return The envelope. + */ + public Envelope envelope(double epsilon) { + return new Envelope( + x-epsilon, x+epsilon, + y-epsilon, y+epsilon); + } + + /** + * Given this and another Point2d it looks if there is + * a gap between the in points in i index direction. + * @param other The other Point2d. + * @return true if there is is a gap, else false. + */ + public boolean hasIGap(Point2d other) { + return Math.abs(i - other.i) > 1; + } + + /** + * Given this and another Point2d it looks if there is + * a gap between the in points in j index direction. + * @param other The other Point2d. + * @return true if there is is a gap, else false. + */ + public boolean hasJGap(Point2d other) { + return Math.abs(j - other.j) > 1; + } + + /** + * Given this and another Point2d a new Point2d is + * created via {@link #newPoint() }. The x, y coordinate + * of the new point is on the line of this and the other + * given point at a given scaling point. + * @param t The scaling factor. + * @param other The other point. + * @return The new Point2d. + */ + public Point2d extrapolate(double t, Point2d other) { + if (other == null) { + return null; + } + Point2d p = newPoint(); + p.x = t*(other.x - x) + x; + p.y = t*(other.y - y) + y; + return p; + } + + /** + * Creates a new Point2d or an instance of a subclass. + * Override this in subclasses. + * @return The new Point2d. + */ + public Point2d newPoint() { + return new Point2d(0d, 0d); + } + + /** + * Creates a new Point2d or an instance of a subclass + * at a given coordinate. + * Override this in subclasses. + * @param x The x coordinate. + * @param y The y coordinate. + * @return The new point. + */ + public Point2d newPoint(double x, double y) { + return new Point2d(x, y); + } + + /** + * Sets the z value to the inverse distance weighting (IDW) value + * of the z values of a set of given points. + * @param ps The points from wich the z values are taken + * to calculate the IDW. + */ + public void inverseDistanceWeighting(Point2d [] ps) { + + double sum = 0d; + + double [] d = new double[ps.length]; + + for (int i = 0; i < ps.length; ++i) { + Point2d p = ps[i]; + if (p != null) { + double di = distance(p); + if (di < 1e-5d) { z = p.z; return; } + di = 1d/di; + d[i] = di; + sum += di; + } + } + + if (sum == 0d) { + return; + } + + double v = 0d; + + for (int i = 0; i < ps.length; ++i) { + Point2d p = ps[i]; + if (p != null) { + v += p.z*d[i]; + } + } + z = v/sum; + } + + /** + * Creates a new point via {@link #newPoint() } with the + * x,y coordinates of the center of a given set of + * coordinates. + * @param ps The points from which the x,y coordinates are + * taken to calculate the center. + * @return The new center point. + */ + public static Point2d average(Point2d [] ps) { + + Point2d p = null; + int count = 0; + + for (int i = 0; i < ps.length; ++i) { + Point2d t = ps[i]; + if (t != null) { + ++count; + if (p == null) { + p = t.newPoint(t.x, t.y); + } + else { + p.x += t.x; + p.y += t.y; + } + } + } + + if (p != null) { + double s = 1d/count; + p.x *= s; + p.y *= s; + } + + return p; + } + + /** + * Checks if this Point2d is near to at least one point + * out of a given set of points. Near is defined by an + * euclidian distance small than {@link #EPSILON}. + * @param ps The set of points to be tested. + * @return true if this Point2d is near to one of the given + * points, else false. + */ + public boolean near(Point2d [] ps) { + + for (int i = 0; i < ps.length; ++i) { + Point2d p = ps[i]; + if (p != null && distance(p) > EPSILON) { + return false; + } + } + + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :