eu.hansolo.tilesfx.tools.Location.java Source code

Java tutorial

Introduction

Here is the source code for eu.hansolo.tilesfx.tools.Location.java

Source

/*
 * Copyright (c) 2017 by Gerrit Grunwald
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package eu.hansolo.tilesfx.tools;

import eu.hansolo.tilesfx.Tile.TileColor;
import eu.hansolo.tilesfx.events.LocationEvent;
import eu.hansolo.tilesfx.events.LocationEventListener;
import org.json.simple.JSONObject;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;

import static eu.hansolo.tilesfx.tools.Helper.clamp;

/**
 * Created by hansolo on 12.02.17.
 */
public class Location {
    public enum CardinalDirection {
        N("North", 348.75, 11.25), NNE("North North-East", 11.25, 33.75), NE("North-East", 33.75, 56.25), ENE(
                "East North-East", 56.25, 78.75), E("East", 78.75, 101.25), ESE("East South-East", 101.25,
                        123.75), SE("South-East", 123.75, 146.25), SSE("South South-East", 146.25, 168.75), S(
                                "South", 168.75, 191.25), SSW("South South-West", 191.25, 213.75), SW("South-West",
                                        213.75, 236.25), WSW("West South-West", 236.25, 258.75), W("West", 258.75,
                                                281.25), WNW("West North-West", 281.25, 303.75), NW("North-West",
                                                        303.75, 326.25), NNW("North North-West", 326.25, 348.75);

        public String direction;
        public double from;
        public double to;

        CardinalDirection(final String DIRECTION, final double FROM, final double TO) {
            direction = DIRECTION;
            from = FROM;
            to = TO;
        }
    }

    private String name;
    private Instant timestamp;
    private double latitude;
    private double longitude;
    private double altitude;
    private String info;
    private TileColor color;
    private int zoomLevel;
    private List<LocationEventListener> listenerList;

    // ******************** Constructors **************************************
    public Location() {
        this(0, 0, 0, Instant.now(), "", "", TileColor.BLUE);
    }

    public Location(final double LATITUDE, final double LONGITUDE) {
        this(LATITUDE, LONGITUDE, 0, Instant.now(), "", "", TileColor.BLUE);
    }

    public Location(final double LATITUDE, final double LONGITUDE, final String NAME) {
        this(LATITUDE, LONGITUDE, 0, Instant.now(), NAME, "", TileColor.BLUE);
    }

    public Location(final double LATITUDE, final double LONGITUDE, final String NAME, final TileColor COLOR) {
        this(LATITUDE, LONGITUDE, 0, Instant.now(), NAME, "", COLOR);
    }

    public Location(final double LATITUDE, final double LONGITUDE, final String NAME, final String INFO) {
        this(LATITUDE, LONGITUDE, 0, Instant.now(), NAME, INFO, TileColor.BLUE);
    }

    public Location(final double LATITUDE, final double LONGITUDE, final String NAME, final String INFO,
            final TileColor COLOR) {
        this(LATITUDE, LONGITUDE, 0, Instant.now(), NAME, INFO, COLOR);
    }

    public Location(final double LATITUDE, final double LONGITUDE, final double ALTITUDE, final String NAME) {
        this(LATITUDE, LONGITUDE, ALTITUDE, Instant.now(), NAME, "", TileColor.BLUE);
    }

    public Location(final double LATITUDE, final double LONGITUDE, final double ALTITUDE, final Instant TIMESTAMP,
            final String NAME) {
        this(LATITUDE, LONGITUDE, ALTITUDE, TIMESTAMP, NAME, "", TileColor.BLUE);
    }

    public Location(final double LATITUDE, final double LONGITUDE, final double ALTITUDE, final Instant TIMESTAMP,
            final String NAME, final String INFO, final TileColor COLOR) {
        name = NAME;
        latitude = LATITUDE;
        longitude = LONGITUDE;
        altitude = ALTITUDE;
        timestamp = TIMESTAMP;
        info = INFO;
        color = COLOR;
        zoomLevel = 15;
        listenerList = new CopyOnWriteArrayList<>();
    }

    // ******************** Methods *******************************************
    public String getName() {
        return name;
    }

    public void setName(final String NAME) {
        name = NAME;
    }

    public Instant getTimestamp() {
        return timestamp;
    }

    public long getTimestampInSeconds() {
        return timestamp.getEpochSecond();
    }

    public void setTimestamp(final Instant TIMESTAMP) {
        timestamp = TIMESTAMP;
    }

    public double getLatitude() {
        return latitude;
    }

    public void setLatitude(final double LATITUDE) {
        latitude = LATITUDE;
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public double getLongitude() {
        return longitude;
    }

    public void setLongitude(final double LONGITUDE) {
        longitude = LONGITUDE;
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public double getAltitude() {
        return altitude;
    }

    public void setAltitude(final double ALTITUDE) {
        altitude = ALTITUDE;
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(final String INFO) {
        info = INFO;
    }

    public TileColor getColor() {
        return color;
    }

    public void setColor(final TileColor COLOR) {
        color = COLOR;
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public ZonedDateTime getZonedDateTime() {
        return getZonedDateTime(ZoneId.systemDefault());
    }

    public ZonedDateTime getZonedDateTime(final ZoneId ZONE_ID) {
        return ZonedDateTime.ofInstant(timestamp, ZONE_ID);
    }

    public int getZoomLevel() {
        return zoomLevel;
    }

    public void setZoomLevel(final int LEVEL) {
        zoomLevel = clamp(0, 17, LEVEL);
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public void update(final double LATITUDE, final double LONGITUDE) {
        set(LATITUDE, LONGITUDE);
    }

    public void set(final double LATITUDE, final double LONGITUDE) {
        latitude = LATITUDE;
        longitude = LONGITUDE;
        timestamp = Instant.now();
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public void set(final double LATITUDE, final double LONGITUDE, final double ALTITUDE, final Instant TIMESTAMP) {
        latitude = LATITUDE;
        longitude = LONGITUDE;
        altitude = ALTITUDE;
        timestamp = TIMESTAMP;
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public void set(final double LATITUDE, final double LONGITUDE, final double ALTITUDE, final Instant TIMESTAMP,
            final String INFO) {
        latitude = LATITUDE;
        longitude = LONGITUDE;
        altitude = ALTITUDE;
        timestamp = TIMESTAMP;
        info = INFO;
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public void set(final Location LOCATION) {
        name = LOCATION.getName();
        latitude = LOCATION.getLatitude();
        longitude = LOCATION.getLongitude();
        altitude = LOCATION.getAltitude();
        timestamp = LOCATION.getTimestamp();
        info = LOCATION.info;
        color = LOCATION.getColor();
        zoomLevel = LOCATION.getZoomLevel();
        fireLocationEvent(new LocationEvent(Location.this));
    }

    public double getDistanceTo(final Location LOCATION) {
        return calcDistanceInMeter(this, LOCATION);
    }

    public boolean isWithinRangeOf(final Location LOCATION, final double METERS) {
        return getDistanceTo(LOCATION) < METERS;
    }

    public double calcDistanceInMeter(final Location P1, final Location P2) {
        return calcDistanceInMeter(P1.getLatitude(), P1.getLongitude(), P2.getLatitude(), P2.getLongitude());
    }

    public double calcDistanceInKilometer(final Location P1, final Location P2) {
        return calcDistanceInMeter(P1, P2) / 1000.0;
    }

    public double calcDistanceInMeter(final double LAT_1, final double LON_1, final double LAT_2,
            final double LON_2) {
        final double EARTH_RADIUS = 6_371_000; // m
        final double LAT_1_RADIANS = Math.toRadians(LAT_1);
        final double LAT_2_RADIANS = Math.toRadians(LAT_2);
        final double DELTA_LAT_RADIANS = Math.toRadians(LAT_2 - LAT_1);
        final double DELTA_LON_RADIANS = Math.toRadians(LON_2 - LON_1);

        final double A = Math.sin(DELTA_LAT_RADIANS * 0.5) * Math.sin(DELTA_LAT_RADIANS * 0.5)
                + Math.cos(LAT_1_RADIANS) * Math.cos(LAT_2_RADIANS) * Math.sin(DELTA_LON_RADIANS * 0.5)
                        * Math.sin(DELTA_LON_RADIANS * 0.5);
        final double C = 2 * Math.atan2(Math.sqrt(A), Math.sqrt(1 - A));

        final double DISTANCE = EARTH_RADIUS * C;

        return DISTANCE;
    }

    public double getAltitudeDifferenceInMeter(final Location LOCATION) {
        return (altitude - LOCATION.getAltitude());
    }

    public double getBearingTo(final Location LOCATION) {
        return calcBearingInDegree(getLatitude(), getLongitude(), LOCATION.getLatitude(), LOCATION.getLongitude());
    }

    public double getBearingTo(final double LATITUDE, final double LONGITUDE) {
        return calcBearingInDegree(getLatitude(), getLongitude(), LATITUDE, LONGITUDE);
    }

    public boolean isZero() {
        return Double.compare(latitude, 0d) == 0 && Double.compare(longitude, 0d) == 0;
    }

    public double calcBearingInDegree(final double LAT_1, final double LON_1, final double LAT_2,
            final double LON_2) {
        double lat1 = Math.toRadians(LAT_1);
        double lon1 = Math.toRadians(LON_1);
        double lat2 = Math.toRadians(LAT_2);
        double lon2 = Math.toRadians(LON_2);
        double deltaLon = lon2 - lon1;
        double deltaPhi = Math.log(Math.tan(lat2 * 0.5 + Math.PI * 0.25) / Math.tan(lat1 * 0.5 + Math.PI * 0.25));
        if (Math.abs(deltaLon) > Math.PI) {
            if (deltaLon > 0) {
                deltaLon = -(2.0 * Math.PI - deltaLon);
            } else {
                deltaLon = (2.0 * Math.PI + deltaLon);
            }
        }
        double bearing = (Math.toDegrees(Math.atan2(deltaLon, deltaPhi)) + 360.0) % 360.0;
        return bearing;
    }

    public String getCardinalDirectionFromBearing(final double BEARING) {
        double bearing = BEARING % 360.0;
        for (CardinalDirection cardinalDirection : CardinalDirection.values()) {
            if (Double.compare(bearing, cardinalDirection.from) >= 0
                    && Double.compare(bearing, cardinalDirection.to) < 0) {
                return cardinalDirection.direction;
            }
        }
        return "";
    }

    // ******************** Event Handling ************************************
    public void setOnLocation(final LocationEventListener LISTENER) {
        addLocationEventListener(LISTENER);
    }

    public void addLocationEventListener(final LocationEventListener LISTENER) {
        if (!listenerList.contains(LISTENER))
            listenerList.add(LISTENER);
    }

    public void removeLocationEventListener(final LocationEventListener LISTENER) {
        if (listenerList.contains(LISTENER))
            listenerList.remove(LISTENER);
    }

    public void fireLocationEvent(final LocationEvent EVENT) {
        for (LocationEventListener listener : listenerList) {
            listener.onLocationEvent(EVENT);
        }
    }

    // ******************** Misc **********************************************
    @Override
    public boolean equals(final Object OBJECT) {
        if (OBJECT instanceof Location) {
            final Location LOCATION = (Location) OBJECT;
            return (Double.compare(latitude, LOCATION.latitude) == 0
                    && Double.compare(longitude, LOCATION.longitude) == 0
                    && Double.compare(altitude, LOCATION.altitude) == 0);
        } else {
            return false;
        }
    }

    public JSONObject toJSON() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("nam", name);
        jsonObject.put("tst", new Long(timestamp.getEpochSecond()));
        jsonObject.put("lat", new Double(latitude));
        jsonObject.put("lon", new Double(longitude));
        jsonObject.put("alt", new Double(altitude));
        jsonObject.put("inf", new String(info));
        jsonObject.put("col", new String(color.toString().replace("0x", "#")));
        jsonObject.put("zml", new Integer(zoomLevel));
        return jsonObject;
    }

    public String toJSONString() {
        return toJSON().toJSONString();
    }

    @Override
    public String toString() {
        return new StringBuilder().append("Name     : ").append(name).append("\n").append("Timestamp: ")
                .append(timestamp).append("\n").append("Latitude : ").append(latitude).append("\n")
                .append("Longitude: ").append(longitude).append("\n").append("Altitude : ")
                .append(String.format(Locale.US, "%.1f", altitude)).append(" m\n").append("Info     : ")
                .append(info).append("\n").append("Color    : ").append(color.toString().replace("0x", "#"))
                .append("\n").append("ZoomLevel: ").append(zoomLevel).append("\n").toString();
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        result = name != null ? name.hashCode() : 0;
        temp = Double.doubleToLongBits(latitude);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(longitude);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(altitude);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }
}