/*
* Copyright 2011
*
* This file is part of Mobile Shuttle Tracker.
*
* Mobile Shuttle Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Mobile Shuttle Tracker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mobile Shuttle Tracker. If not, see <http://www.gnu.org/licenses/>.
*/
package com.abstractedsheep.world;
public class Coordinate {
private double latitude;
private double longitude;
private static final double RADIUS_OF_EARTH = 3956;
public Coordinate() {
this.latitude = 0.0;
this.longitude = 0.0;
}
/**
* @param latitude - latitude in degrees (double value)
* @param longitude - longitude in degrees (double value)
*/
public Coordinate(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
/**
* @return the latitude
*/
public double getLatitude() {
return latitude;
}
/**
* @param latitude the latitude to set
*/
public void setLatitude(double latitude) {
this.latitude = latitude;
}
/**
* @return the longitude
*/
public double getLongitude() {
return longitude;
}
/**
* @param longitude the longitude to set
*/
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public static boolean sameCoordinates(Coordinate c1, Coordinate c2) {
return false;
}
public double distanceFromCoordiante(Coordinate c) {
double dLong = Math.toRadians((c.getLongitude() - this.getLongitude()));
double dLat = Math.toRadians((c.getLatitude() - this.getLatitude()));
double lat1 = Math.toRadians(this.getLatitude());
double lat2 = Math.toRadians(c.getLatitude());
double a = Math.pow(Math.sin(dLat / 2.0), 2)
+ Math.pow(Math.sin(dLong / 2.0), 2) * Math.cos(lat1)
* Math.cos(lat2);
double b = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1.0 - a));
return RADIUS_OF_EARTH * b;
}
/**
* This class really has no use except for in the DynamicDataGenerator
* class
*
* @param distance - distance from current point
* @param endPoint - end point of line
* @return the coordinate point some distance away from the current coordinate
*/
public Coordinate findCoordinateInLine(double distance, Coordinate endPoint) {
distance = distance / RADIUS_OF_EARTH;
double bearing = this.getBearing(endPoint);
double lon1 = Math.toRadians(this.getLongitude());
double lat1 = Math.toRadians(this.getLatitude());
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(distance)
+ Math.cos(lat1) * Math.sin(distance) * Math.cos(bearing));
double lon2 = lon1 +
Math.atan2(Math.sin(bearing) * Math.sin(distance) * Math.cos(lat1),
Math.cos(distance) - Math.sin(lat1) * Math.sin(lat2));
return new Coordinate(Math.toDegrees(lat2), Math.toDegrees(lon2));
}
public double getBearing(Coordinate c) {
double delta = Math.toRadians((this.getLongitude() - c.getLongitude()));
double lat1 = Math.toRadians(c.getLatitude());
double lat2 = Math.toRadians(this.getLatitude());
double y = Math.sin(delta) * Math.cos(lat1);
double x = Math.cos(lat2) * Math.sin(lat1) - Math.sin(lat2)
* Math.cos(lat1) * Math.cos(delta);
return Math.toDegrees(Math.atan2(y, x));
}
/**
* Calculates the closet coordinate point in the line constructed by the
* below paramaters
*
* @param endPoint1 - one end point defining the line
* @param endPoint2 - another end point defining the line
* @return the closest coordinate point between the two given points.
*/
public Coordinate closestPoint(Coordinate endPoint1, Coordinate endPoint2) {
final int R = 3956;
Point3D pt1 = new Point3D(R
* Math.cos(Math.toRadians(endPoint1.getLatitude()))
* Math.cos(Math.toRadians(endPoint1.getLongitude())), R
* Math.cos(Math.toRadians(endPoint1.getLatitude()))
* Math.sin(Math.toRadians(endPoint1.getLongitude())), R
* Math.sin(Math.toRadians(endPoint1.getLatitude())));
Point3D pt2 = new Point3D(R
* Math.cos(Math.toRadians(endPoint2.getLatitude()))
* Math.cos(Math.toRadians(endPoint2.getLongitude())), R
* Math.cos(Math.toRadians(endPoint2.getLatitude()))
* Math.sin(Math.toRadians(endPoint2.getLongitude())), R
* Math.sin(Math.toRadians(endPoint2.getLatitude())));
Point3D pt3 = new Point3D(R
* Math.cos(Math.toRadians(this.getLatitude()))
* Math.cos(Math.toRadians(this.getLongitude())), R
* Math.cos(Math.toRadians(this.getLatitude()))
* Math.sin(Math.toRadians(this.getLongitude())), R
* Math.sin(Math.toRadians(this.getLatitude())));
Point3D origin = new Point3D();
Point3D delta1 = Point3D.subtract(pt3, pt2);
Point3D delta2 = Point3D.subtract(pt3, pt1);
Point3D delta3 = Point3D.subtract(pt2, pt1);
double d = (delta1.crossProduct(delta2)).getMagnitude()
/ delta3.getMagnitude();
double hypothenuse = pt3.DistanceTo(pt1);
double theta = Math.asin(d / hypothenuse);
double adj = (d / Math.tan(theta));
Point3D closestPt = pt1.moveTowards(pt2, adj);
Point3D surfacePt = origin.moveTowards(closestPt, R);
return new Coordinate(
(Math.toDegrees((Math.asin(surfacePt.getZ() / R)))),
(Math.toDegrees((Math.atan2(surfacePt.getY(), surfacePt.getX())))));
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!(obj instanceof Coordinate))
return false;
Coordinate c = (Coordinate) obj;
return (c.getLatitude() == this.getLatitude())
&& (c.getLongitude() == this.getLongitude());
}
@Override
public String toString() {
return String.format("(%g, %g)", new Object[] {this.getLatitude(), this.getLongitude() });
}
}