001 // License: GPL. Copyright 2007 by Immanuel Scholz and others
002 package org.openstreetmap.josm.data.coor;
003
004 /**
005 * Northing, Easting of the projected coordinates.
006 *
007 * This class is immutable.
008 *
009 * @author Imi
010 */
011 public class EastNorth extends Coordinate {
012
013 public EastNorth(double east, double north) {
014 super(east,north);
015 }
016
017 public double east() {
018 return x;
019 }
020
021 public double north() {
022 return y;
023 }
024
025 public EastNorth add(double dx, double dy) {
026 return new EastNorth(x+dx, y+dy);
027 }
028
029 public EastNorth add(EastNorth other) {
030 return new EastNorth(x+other.x, y+other.y);
031 }
032
033 public EastNorth scale(double s) {
034 return new EastNorth(s * x, s * y);
035 }
036
037 public EastNorth interpolate(EastNorth en2, double proportion) {
038 return new EastNorth(this.x + proportion * (en2.x - this.x),
039 this.y + proportion * (en2.y - this.y));
040 }
041
042 public EastNorth getCenter(EastNorth en2) {
043 return new EastNorth((this.x + en2.x)/2.0, (this.y + en2.y)/2.0);
044 }
045
046 public double distance(EastNorth en2) {
047 return Math.sqrt((this.x-en2.x)*(this.x-en2.x) + (this.y-en2.y)*(this.y-en2.y));
048 }
049
050 /**
051 * Returns the heading, in radians, that you have to use to get from
052 * this EastNorth to another. Heading is mapped into [0, 2pi)
053 *
054 * @param other the "destination" position
055 * @return heading
056 */
057 public double heading(EastNorth other) {
058 double hd = Math.atan2(other.east() - east(), other.north() - north());
059 if(hd < 0) hd = 2 * Math.PI + hd;
060 return hd;
061 }
062
063 /**
064 * Replies true if east and north are different from Double.NaN
065 *
066 * @return true if east and north are different from Double.NaN
067 */
068 public boolean isValid() {
069 return !java.lang.Double.isNaN(x) && !java.lang.Double.isNaN(y);
070 }
071
072 public EastNorth sub(EastNorth en) {
073 return new EastNorth(en.east() - east(), en.north() - north());
074 }
075
076 /**
077 * Returns an EastNorth representing the this EastNorth rotated around
078 * a given EastNorth by a given angle
079 * @param pivot the center of the rotation
080 * @param angle the angle of the rotation
081 * @return EastNorth rotated object
082 */
083 public EastNorth rotate(EastNorth pivot, double angle) {
084 double cosPhi = Math.cos(angle);
085 double sinPhi = Math.sin(angle);
086 double x = east() - pivot.east();
087 double y = north() - pivot.north();
088 double nx = cosPhi * x + sinPhi * y + pivot.east();
089 double ny = -sinPhi * x + cosPhi * y + pivot.north();
090 return new EastNorth(nx, ny);
091 }
092
093 @Override public String toString() {
094 return "EastNorth[e="+x+", n="+y+"]";
095 }
096
097 /**
098 * Compares two EastNorth values
099 *
100 * @return true if "x" and "y" values are within 1E-6 of each other
101 */
102 public boolean equalsEpsilon(EastNorth other, double e) {
103 return (Math.abs(x - other.x) < e && Math.abs(y - other.y) < e);
104 }
105 }