/*
* Copyright (C) 2010- Peer internet solutions
*
* This file is part of mixare.
*
* This program 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.
*
* This program 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
* this program. If not, see <http://www.gnu.org/licenses/>
*/
package org.mixare.lib.reality;
import org.mixare.lib.render.MixVector;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
/**
* The class stores the geographical information (latitude, longitude and
* altitude) and represents a Place on the map. It also calculates the
* destination using the theory of the great-circle-distance. Further it is able
* to convert the distances between locations into vectors and vice versa.
*
*/
public class PhysicalPlace implements Parcelable {
double latitude;
double longitude;
double altitude;
public PhysicalPlace() {
}
public static final Parcelable.Creator<PhysicalPlace> CREATOR = new Parcelable.Creator<PhysicalPlace>() {
public PhysicalPlace createFromParcel(Parcel in) {
return new PhysicalPlace(in);
}
public PhysicalPlace[] newArray(int size) {
return new PhysicalPlace[size];
}
};
public PhysicalPlace(Parcel in){
readParcel(in);
}
public PhysicalPlace(PhysicalPlace pl) {
this.setTo(pl.latitude, pl.longitude, pl.altitude);
}
public PhysicalPlace(double latitude, double longitude, double altitude) {
this.setTo(latitude, longitude, altitude);
}
public void setTo(double latitude, double longitude, double altitude) {
this.latitude = latitude;
this.longitude = longitude;
this.altitude = altitude;
}
public void setTo(PhysicalPlace pl) {
this.latitude = pl.latitude;
this.longitude = pl.longitude;
this.altitude = pl.altitude;
}
@Override
public String toString() {
return "(lat=" + latitude + ", lng=" + longitude + ", alt=" + altitude
+ ")";
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getAltitude() {
return altitude;
}
public void setAltitude(double altitude) {
this.altitude = altitude;
}
public static void calcDestination(double lat1Deg, double lon1Deg,
double bear, double d, PhysicalPlace dest) {
/** see http://en.wikipedia.org/wiki/Great-circle_distance */
double brng = Math.toRadians(bear);
double lat1 = Math.toRadians(lat1Deg);
double lon1 = Math.toRadians(lon1Deg);
double R = 6371.0 * 1000.0;
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(d / R)
+ Math.cos(lat1) * Math.sin(d / R) * Math.cos(brng));
double lon2 = lon1
+ Math.atan2(Math.sin(brng) * Math.sin(d / R) * Math.cos(lat1),
Math.cos(d / R) - Math.sin(lat1) * Math.sin(lat2));
dest.setLatitude(Math.toDegrees(lat2));
dest.setLongitude(Math.toDegrees(lon2));
}
public static void convLocToVec(Location org, PhysicalPlace gp, MixVector v) {
float[] z = new float[1];
z[0] = 0;
Location.distanceBetween(org.getLatitude(), org.getLongitude(),
gp.getLatitude(), org.getLongitude(), z);
float[] x = new float[1];
Location.distanceBetween(org.getLatitude(), org.getLongitude(),
org.getLatitude(), gp.getLongitude(), x);
double y = gp.getAltitude() - org.getAltitude();
if (org.getLatitude() < gp.getLatitude())
z[0] *= -1;
if (org.getLongitude() > gp.getLongitude())
x[0] *= -1;
v.set(x[0], (float) y, z[0]);
}
public static void convertVecToLoc(MixVector v, Location org, Location gp) {
double brngNS = 0, brngEW = 90;
if (v.z > 0)
brngNS = 180;
if (v.x < 0)
brngEW = 270;
PhysicalPlace tmp1Loc = new PhysicalPlace();
PhysicalPlace tmp2Loc = new PhysicalPlace();
PhysicalPlace.calcDestination(org.getLatitude(), org.getLongitude(),
brngNS, Math.abs(v.z), tmp1Loc);
PhysicalPlace.calcDestination(tmp1Loc.getLatitude(),
tmp1Loc.getLongitude(), brngEW, Math.abs(v.x), tmp2Loc);
gp.setLatitude(tmp2Loc.getLatitude());
gp.setLongitude(tmp2Loc.getLongitude());
gp.setAltitude(org.getAltitude() + v.y);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeDouble(latitude);
dest.writeDouble(longitude);
dest.writeDouble(altitude);
}
public void readParcel(Parcel in) {
latitude = in.readDouble();
longitude = in.readDouble();
altitude = in.readDouble();
}
}