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