package com.circlegate.liban.location; import org.json.JSONException; import org.json.JSONObject; import android.location.Location; import com.circlegate.liban.base.ApiBase.ApiCreator; import com.circlegate.liban.base.ApiBase.ApiParcelable; import com.circlegate.liban.base.ApiDataIO.ApiDataInput; import com.circlegate.liban.base.ApiDataIO.ApiDataOutput; public class LocPoint extends ApiParcelable implements Comparable<LocPoint> { // zdroj: http://www.csgnetwork.com/degreelenllavcalc.html // jeden stupen sirky v metrech public static final int ONE_DEGREE_LATITUDE_IN_METERS = 111229; // jeden stupen delky v metrech (pro padesatou rovnobezku) public static final int ONE_DEGREE_LONGTITUDE_IN_METERS = 71695; private static final int MAX_LAT = 90000000; private static final int MAX_LNG = 180000000; public static final LocPoint INVALID = new LocPoint(0, 0); private final double latitude; private final double longitude; //private final LatLng latLng; // public static LocPoint createFromJson(JSONObject json, String keyLat, String keyLng, boolean optional) throws JSONException { // if ((json.isNull(keyLat) || json.isNull(keyLng)) && !optional) { // throw new JSONException("Missing lat/lng"); // } // // LocPoint ret = new LocPoint(json.optDouble(keyLat, 0), json.optDouble(keyLng, 0)); // // if (!ret.isValid()) // if (!optional) // throw new JSONException("Invalid lat/lng"); // else // return null; // else // return ret; // } public LocPoint(int latitudeE6, int longitudeE6) { this((double)latitudeE6 / 1E6, (double)longitudeE6 / 1E6); } public LocPoint(double latitude, double longitude) { this.latitude = latitude; this.longitude = longitude; //this(new LatLng(latitude, longitude)); } // public LocPoint(LatLng latLng) { // this.latLng = latLng; // } public LocPoint(Location location) { this(location.getLatitude(), location.getLongitude()); } public LocPoint(ApiDataInput d) { this.latitude = d.readDouble(); this.longitude = d.readDouble(); //this.latLng = new LatLng(lat, lng); } @Override public void save(ApiDataOutput d, int flags) { d.write(this.latitude); d.write(this.longitude); } public JSONObject appendToJSON(JSONObject json, String keyLat, String keyLng) { try { json.put(keyLat, getLatitude()); json.put(keyLng, getLongitude()); return json; } catch (JSONException ex) { throw new RuntimeException(ex); } } // public LatLng getLatLng() { // return this.latLng; // } public int getLatitudeE6() { return (int)(this.latitude * 1E6); } public int getLongitudeE6() { return (int)(this.longitude * 1E6); } public double getLatitude() { return this.latitude; } public double getLongitude() { return this.longitude; } public String getLatitudeString() { return getFormattedLatLng(getLatitudeE6()); } public String getLongitudeString() { return getFormattedLatLng(getLongitudeE6()); } public String getLatitudeStringDMS() { return (latitude >= 0 ? "N" : "S") + decimalToDMS(Math.abs(latitude)); } public String getLongitudeStringDMS() { return (longitude >= 0 ? "E" : "W") + decimalToDMS(Math.abs(longitude)); } public boolean isValid() { return isValid(this); } @Override public int hashCode() { int _hash = 17; _hash = _hash * 29 + getLatitudeE6(); _hash = _hash * 29 + getLongitudeE6(); return _hash; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof LocPoint)) { return false; } LocPoint lhs = (LocPoint) o; return lhs != null && getLatitudeE6() == lhs.getLatitudeE6() && getLongitudeE6() == lhs.getLongitudeE6(); } @Override public String toString() { return getFormattedLatLng(latitude) + ", " + getFormattedLatLng(longitude); } @Override public int compareTo(LocPoint another) { if (getLatitudeE6() != another.getLatitudeE6()) return getLatitudeE6() < another.getLatitudeE6() ? -1 : 1; else if (getLongitudeE6() != another.getLongitudeE6()) return getLongitudeE6() < another.getLongitudeE6() ? -1 : 1; else return 0; } public static boolean isValid(LocPoint locPoint) { return Math.round(locPoint.latitude * 1E6) != 0 || Math.round(locPoint.longitude * 1E6) != 0; } public static int normalizeLat(int lat) { return Math.max(-MAX_LAT, Math.min(MAX_LAT, lat)); } public static int normalizeLng(int lng) { while (lng > MAX_LNG) lng -= 2 * MAX_LNG; while (lng < -MAX_LNG) lng += 2 * MAX_LNG; return lng; } public static String getFormattedLatLng(double value) { return getFormattedLatLng((int)Math.round(value * 1E6)); } public static String getFormattedLatLng(int valueE6) { String ret = "" + (Math.abs(valueE6) % 1000000); while (ret.length() < 6) ret = "0" + ret; ret = "" + (valueE6 / 1000000) + "." + ret; return ret; //return format.format(value); } public double getDistanceFrom(LocPoint other) { return getDistance(this, other); } public double getDistanceFrom(double lat, double lng) { return getDistance(this.getLatitude(), this.getLongitude(), lat, lng); } public static double getDistance(LocPoint first, LocPoint second) { return getDistance(first.getLatitude(), first.getLongitude(), second.getLatitude(), second.getLongitude()); } /** * Vraci vzdalenost v metrech */ public static double getDistance(double nLat1, double nLong1, double nLat2, double nLong2) { double nTheta = nLong1 - nLong2; double nDist = Math.sin(degreesToRadians(nLat1)) * Math.sin(degreesToRadians(nLat2)) + Math.cos(degreesToRadians(nLat1)) * Math.cos(degreesToRadians(nLat2)) * Math.cos(degreesToRadians(nTheta)); nDist = Math.acos(nDist); nDist = radiansToDegrees(nDist); double nRet = nDist * 60 * 1.1515 * 1.609344 * 1000; return Double.isNaN(nRet) ? 0 : nRet; } public static LocPoint getGpsByBaseGpsAndDistanceAndAzimuth(double latitude, double longitude, double distance, double azimuth) { final double rEarth = 6371.01; // Earth's average radius in km final double epsilon = 0.000001; // threshold for floating-point equality double rlat1 = degreesToRadians(latitude); double rlon1 = degreesToRadians(longitude); double rbearing = degreesToRadians(azimuth) * -1; // to * -1 jsem tam dal, aby nebyl otoceny vychod/zapad double rdistance = distance / (rEarth * 1000); // normalize linear distance to radian angle double rlat = Math.asin(Math.sin(rlat1) * Math.cos(rdistance) + Math.cos(rlat1) * Math.sin(rdistance) * Math.cos(rbearing)); double rlon; if (Math.cos(rlat) == 0 || Math.abs(Math.cos(rlat)) < epsilon) // Endpoint a pole rlon = rlon1; else rlon = ((rlon1 - Math.asin(Math.sin(rbearing) * Math.sin(rdistance) / Math.cos(rlat)) + Math.PI) % (2 * Math.PI)) - Math.PI; LocPoint ret = new LocPoint(radiansToDegrees(rlat), radiansToDegrees(rlon)); return ret; } public static double getDistSquare(double dX1, double dY1, double dX2, double dY2) { dX2 -= dX1; dX2 *= ONE_DEGREE_LATITUDE_IN_METERS; dY2 -= dY1; dY2 *= ONE_DEGREE_LONGTITUDE_IN_METERS; return dX2 * dX2 + dY2 * dY2; } private static double radiansToDegrees(double dRadians) { return (double)(dRadians * (180.0 / Math.PI)); } private static double degreesToRadians(double nDegrees) { return (double)(Math.PI * nDegrees / 180.0); } // Input a double latitude or longitude in the decimal format // e.g. 87.728056 public static String decimalToDMS(double coord) { String output, degrees, minutes, seconds; // gets the modulus the coordinate divided by one (MOD1). // in other words gets all the numbers after the decimal point. // e.g. mod = 87.728056 % 1 == 0.728056 // // next get the integer part of the coord. On other words the whole number part. // e.g. intPart = 87 double mod = coord % 1; int intPart = (int)coord; //set degrees to the value of intPart //e.g. degrees = "87" degrees = String.valueOf(intPart); // next times the MOD1 of degrees by 60 so we can find the integer part for minutes. // get the MOD1 of the new coord to find the numbers after the decimal point. // e.g. coord = 0.728056 * 60 == 43.68336 // mod = 43.68336 % 1 == 0.68336 // // next get the value of the integer part of the coord. // e.g. intPart = 43 coord = mod * 60; mod = coord % 1; intPart = (int)coord; // set minutes to the value of intPart. // e.g. minutes = "43" minutes = String.valueOf(intPart); //do the same again for minutes //e.g. coord = 0.68336 * 60 == 41.0016 //e.g. intPart = 41 coord = mod * 60; intPart = (int)coord; // set seconds to the value of intPart. // e.g. seconds = "41" seconds = String.valueOf(intPart); //Standard output of D°M′S″ output = degrees + "°" + minutes + "'" + seconds + "\""; return output; } /* * Conversion DMS to decimal * * Input: latitude or longitude in the DMS format ( example: N 43° 36' 15.894") * Return: latitude or longitude in decimal format * hemisphereOUmeridien => {W,E,S,N} * */ public static double DMSToDecimal(String hemisphereOUmeridien, double degres, double minutes, double secondes) { double LatOrLon=0; double signe=1.0; if((hemisphereOUmeridien=="W")||(hemisphereOUmeridien=="S")) {signe=-1.0;} LatOrLon = signe*(Math.floor(degres) + Math.floor(minutes)/60.0 + secondes/3600.0); return(LatOrLon); } public static final ApiCreator<LocPoint> CREATOR = new ApiCreator<LocPoint>() { public LocPoint create(ApiDataInput d) { return new LocPoint(d); } public LocPoint[] newArray(int size) { return new LocPoint[size]; } }; }