001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.coor;
003
004import java.util.Objects;
005
006import org.openstreetmap.josm.data.projection.Projecting;
007import org.openstreetmap.josm.data.projection.Projection;
008import org.openstreetmap.josm.data.projection.ProjectionRegistry;
009
010/**
011 * LatLon class that maintains a cache of projected EastNorth coordinates.
012 *
013 * This class is convenient to use, but has relatively high memory costs.
014 * It keeps a pointer to the last known projection in order to detect projection changes.
015 *
016 * Node and WayPoint have another, optimized, cache for projected coordinates.
017 */
018public class CachedLatLon extends LatLon {
019
020    private static final long serialVersionUID = 1L;
021
022    private EastNorth eastNorth;
023    private transient Object cacheKey;
024
025    /**
026     * Constructs a new {@code CachedLatLon}.
027     * @param lat latitude
028     * @param lon longitude
029     */
030    public CachedLatLon(double lat, double lon) {
031        super(lat, lon);
032    }
033
034    /**
035     * Constructs a new {@code CachedLatLon}.
036     * @param coor lat/lon
037     */
038    public CachedLatLon(LatLon coor) {
039        super(coor.lat(), coor.lon());
040        cacheKey = null;
041    }
042
043    /**
044     * Constructs a new {@code CachedLatLon}.
045     * @param eastNorth easting/northing
046     */
047    public CachedLatLon(EastNorth eastNorth) {
048        this(eastNorth, ProjectionRegistry.getProjection());
049    }
050
051    private CachedLatLon(EastNorth eastNorth, Projection projection) {
052        super(projection.eastNorth2latlon(eastNorth));
053        cacheKey = projection.getCacheKey();
054        this.eastNorth = eastNorth;
055    }
056
057    /**
058     * Replies the projected east/north coordinates.
059     *
060     * @return the internally cached east/north coordinates. null, if the globally defined projection is null
061     */
062    @Override
063    public final EastNorth getEastNorth(Projecting projecting) {
064        if (!Objects.equals(cacheKey, projecting.getCacheKey())) {
065            cacheKey = projecting.getCacheKey();
066            eastNorth = projecting.latlon2eastNorth(this);
067        }
068        return eastNorth;
069    }
070
071    @Override
072    public int hashCode() {
073        return Objects.hash(x, y, eastNorth);
074    }
075
076    @Override
077    public boolean equals(Object obj) {
078        if (!super.equals(obj))
079            return false;
080        CachedLatLon other = (CachedLatLon) obj;
081        return Objects.equals(eastNorth, other.eastNorth);
082    }
083
084    @Override
085    public String toString() {
086        return "CachedLatLon[lat="+lat()+",lon="+lon()+']';
087    }
088}