001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.coor;
003
004import java.io.Serializable;
005import java.util.Objects;
006
007import org.openstreetmap.josm.data.osm.BBox;
008
009/**
010 * Base class of points of both coordinate systems.
011 *
012 * The variables are default package protected to allow routines in the
013 * data package to access them directly.
014 *
015 * As the class itself is package protected too, it is not visible
016 * outside of the data package. Routines there should only use LatLon or
017 * EastNorth.
018 *
019 * @since 6162
020 */
021abstract class Coordinate implements Serializable {
022
023    protected final double x;
024    protected final double y;
025
026    /**
027     * Construct the point with latitude / longitude values.
028     *
029     * @param x X coordinate of the point.
030     * @param y Y coordinate of the point.
031     */
032    Coordinate(double x, double y) {
033        this.x = x; this.y = y;
034    }
035
036    public double getX() {
037        return x;
038    }
039
040    public double getY() {
041        return y;
042    }
043
044    /**
045     * Returns the euclidean distance from this {@code Coordinate} to a specified {@code Coordinate}.
046     *
047     * @param coor the specified coordinate to be measured against this {@code Coordinate}
048     * @return the euclidean distance from this {@code Coordinate} to a specified {@code Coordinate}
049     * @since 6166
050     */
051    protected final double distance(final Coordinate coor) {
052        return distance(coor.x, coor.y);
053    }
054
055    /**
056     * Returns the euclidean distance from this {@code Coordinate} to a specified coordinate.
057     *
058     * @param px the X coordinate of the specified point to be measured against this {@code Coordinate}
059     * @param py the Y coordinate of the specified point to be measured against this {@code Coordinate}
060     * @return the euclidean distance from this {@code Coordinate} to a specified coordinate
061     * @since 6166
062     */
063    public final double distance(final double px, final double py) {
064        final double dx = this.x-px;
065        final double dy = this.y-py;
066        return Math.sqrt(dx*dx + dy*dy);
067    }
068
069    /**
070     * Returns the square of the euclidean distance from this {@code Coordinate} to a specified {@code Coordinate}.
071     *
072     * @param coor the specified coordinate to be measured against this {@code Coordinate}
073     * @return the square of the euclidean distance from this {@code Coordinate} to a specified {@code Coordinate}
074     * @since 6166
075     */
076    protected final double distanceSq(final Coordinate coor) {
077        return distanceSq(coor.x, coor.y);
078    }
079
080    /**
081     * Returns the square of euclidean distance from this {@code Coordinate} to a specified coordinate.
082     *
083     * @param px the X coordinate of the specified point to be measured against this {@code Coordinate}
084     * @param py the Y coordinate of the specified point to be measured against this {@code Coordinate}
085     * @return the square of the euclidean distance from this {@code Coordinate} to a specified coordinate
086     * @since 6166
087     */
088    public final double distanceSq(final double px, final double py) {
089        final double dx = this.x-px;
090        final double dy = this.y-py;
091        return dx*dx + dy*dy;
092    }
093
094    /**
095     * Creates bbox around this coordinate. Coordinate defines
096     * center of bbox, its edge will be 2*r.
097     *
098     * @param r size
099     * @return BBox around this coordinate
100     * @since 6203
101     */
102    public BBox toBBox(final double r) {
103        return new BBox(x - r, y - r, x + r, y + r);
104    }
105
106    @Override
107    public int hashCode() {
108        return Objects.hash(x, y);
109    }
110
111    @Override
112    public boolean equals(Object obj) {
113        if (this == obj) return true;
114        if (obj == null || getClass() != obj.getClass()) return false;
115        Coordinate that = (Coordinate) obj;
116        return Double.compare(that.x, x) == 0 &&
117                Double.compare(that.y, y) == 0;
118    }
119}