I took the code of compass from this link.
http://www.androidcode.ninja/android-compass-code-example/
How to set mecca location on my compass??
What do i need to do to point my compass to Mecca?
You need to determine your location relatively to Mecca, so you will need Location permission and implement Location Updates.
You can implement that using: Receveing location updates
With this information you can determine where Mecca would be on your compass and set it accordingly. To determine the angle, use this code:
private double angleFromCoordinate(double lat1, double long1, double lat2,
double long2) {
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
brng = 360 - brng; // count degrees counter-clockwise - remove to make clockwise
return brng;
}
from: Calculate angle between two Latitude/Longitude points
Well for very few words that's a long question. The answer is to extend the OnSensorChanged code from the example to calculate the heading to Mecca from the current location and adjust the heading based on the current direction the sensor is facing in. You'll need the current location co-ordinates from GPS and the fixed co-ordintates for Mecca, Calculate the direction relative to North (the way the compass is designed to point) and then adjust by the current heading.
Related
I want to create an app in which I want to show how much distance does the user has been traveled.
I have tried using float distance = locationA.distanceTo(locationB); but it just draws a simple straight line from start to end and then calculates the distance.
I want to calculate the traveled distance based on the traveled route. Is it possible to do so using any Google maps API?
you just need service to continuously observer that user change it's location then you can use these function to calculate the distance.
public double GetDistanceInKm(double lat1, double lon1, double lat2, double lon2)
{
final int R = 6371;
// Radius of the earth in km
double dLat = deg2rad(lat2 - lat1);
// deg2rad below
double dLon = deg2rad(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = R * c;
// Distance in km
return d;
}
private double deg2rad(double deg)
{
return deg * (Math.PI / 180);
}
Assuming you have a bunch of lat long points making up a route. You have to take the distance from the previous point to the next point for all points and keep a total of that. In other words you need a-lot of lat lon data in between the route or you are just going to get a straight line.
You can use google maps api to get the distance
use this link to understand how to use it.
I'm trying to make a compass that points to a custom location in a Unity program. However it's completely off, it points in generally the wrong direction and I can't quite seem to figure out what is wrong with my logic.
I'm using the curved geometry bearing equation from here: http://www.yourhomenow.com/house/haversine.html
Get current location.
Calculate bearing from current location to target location.
Rotate screen compass relative to true north.
// Calculate bearing between current location and target location
// Get current GPS location
float lat1 = Input.location.lastData.latitude;
float lon1 = Input.location.lastData.longitude;
float lat2 = TargetLatitude;
float dLon = TargetLongitude - lon1;
// Calculate bearing
var y = Mathf.Sin(dLon) * Mathf.Cos(lat2);
var x = Mathf.Cos(lat1) * Mathf.Sin(lat2) -
Mathf.Sin(lat1) * Mathf.Cos(lat2) * Mathf.Cos(dLon);
var brng = ((Mathf.Atan2(y, x)*(180.0f/Mathf.PI)) + 360.0f) % 360.0f;
Dump.text = brng.ToString();
// Rotate the to target location relative to north. Z axis pointing out of screen.
transform.eulerAngles = new Vector3(0, 0, Mathf.MoveTowardsAngle(transform.localEulerAngles.z, Input.compass.trueHeading + brng, COMPASS_MAXDELTA));
If I remove the bearing offset in that code, it points north enough for a digital compass.
Make sure that all of your angles are in radians rather than degrees.
Using Mathf.Deg2Rad in cases such as Mathf.Sin(dLon * Mathf.Deg2Rad) should yield the correct result. The Haversine formula only works for angles in radians.
I have a little project I've been playing with (Android, GPS, mapping APIs), and I need to figure how to find a longitude/latitude/GeoPoint from a given longitude/latitude/GeoPoint with only knowing the meters/km longitude and latitude. e.g. I want to figure out where a point is from me, that I know is +1000 meters along the longitude and +1000 along the latitude.
It's a little different than the usual GeoPoint/distance questions you'll see, and it's not quite geo fencing radius related as the distance is X,Y meters/kms, and I don't have a bearing. (I could work out a bearing, but I don't have a suitable direct distance)
Basically, if I could reverse GeoPoint.distanceTo() it would do the job for me.
Update
Just a little more background. I'm basically applying a node triangulation idea I had, but the algorithm requires that my inputs be in a map normalized form that's not the same as longitude and latitude. I create a map/grid where 0,0 (the bottom/left) is the left/west and bottom/south most longitude/latitude values from the nodes I'm working with. All the other node X/Y on the map are determined by finding their meters from the 0,0 node's longitude/latitude using GeoPoint.distanceTo(). (note that I find their X/Y by performing distanceTo twice for each node so I have the X and Y meters from 0,0, not a direct line to the node) That distance in meters is fed into the algorithm and new X/Y map points are produced.
And so I need to figure out how to convert distance from a longitude/latitude into another, previously unknown, longitude/latitude.
double startPointLongitude = 23.459821;
double startPointLatitude = 76.998200;
double distanceLongitude = 100; // 100 meters along the longitude
double distanceLatitude = 75; // 75 meters along the latitude
Basically i took the Answer from AlexWien, corrected two things and made it into a java method
private static final double WGS84_RADIUS = 6370997.0;
private static double EarthCircumFence = 2* WGS84_RADIUS * Math.PI;
private static Position getPosition(Position sourcePosition, double mEastWest, double mNorthSouth){
double degreesPerMeterForLat = EarthCircumFence/360.0;
double shrinkFactor = Math.cos((sourcePosition.getLat()*Math.PI/180));
double degreesPerMeterForLon = degreesPerMeterForLat * shrinkFactor;
double newLat = sourcePosition.getLat() + mNorthSouth * (1/degreesPerMeterForLat);
double newLng = sourcePosition.getLng() + mEastWest * (1/degreesPerMeterForLon);
return new Position(newLat, newLng);
}
The distance between two degrees of latitude never change, it is always aprox. 111 km
(The exact value you should caculate by using the WGS84 Earth radius:
EarthCircumFence = 2* WGS84_RADIUS * Math.Pi;
metersPerDegree = (Earth Cirumfence / 360)
With this info you easily can calculate the latitude offset,
just reverse the factor and have:
degreesPerMeterForLat = EarthCircumfenceMeter / 360.0
with longitude its a bit different, the distance between two degrees of longitude shrink
the more you move away from aequator.
shrinkFactor = cos(toRadians(locationLatitude));
compensate now:
degreesPerMeterForLon = degreesPerMeterForLat / shrinkFactor;
Finally
newLatPos = latOld + numMeters * degreesPerMeterForLat;
newLonPos = lonOld + numMeters * degreesPerMeterForLon;
This works for distance offset < 10 - 50 km
Sigh, I posted this like 6 hours ago but it does not appear to have gone through.
Ok, worked it out in spite of most geographical formulas and facts occasionally going over my head. Working with geography is like working with the Gregorian calendar, it makes sense if you program for it all the time, but otherwise it's easy to get confused by an incorrect assumption.
The following except from my app will take a starting GeoPoint's long/lat
/**
* the length of one degree of latitude (and one degree of longitude at equator) in meters.
*/
private static final double DEGREE_DISTANCE_AT_EQUATOR = 111329;
/**
* calculates the x,y in meters from a given starting point's long0, lat0 to a target destination point's long1, lat1.
* #param long0 start point longitude
* #param lat0 start point latitude
* #param long1 end point longitude
* #param lat1 end point latitude
* #return
*/
public static Pair<Double, Double> xyFromLongLat(int long0, int lat0, int long1, int lat1) {
double x = (long1 / 1E6 - long0 / 1E6) * longitudeDistanceAtLatitude(lat0 / 1E6);
double y = (lat1 / 1E6 - lat0 / 1E6) * DEGREE_DISTANCE_AT_EQUATOR;
return new Pair<Double, Double>(x, y);
}
/**
* calculates longitude and latitude from a given starting point, with only the X/Y meters
* #param long0
* #param lat0
* #param x
* #param y
* #return
*/
public static Pair<Double, Double> longLatFromXY(int long0, int lat0, double x, double y) {
double lat1 = (y / DEGREE_DISTANCE_AT_EQUATOR) + (lat0 / 1E6);
double long1 = x / longitudeDistanceAtLatitude(lat0) + (long0 / 1E6);
return new Pair<Double, Double>(lat1, long1);
}
Found a plenty of answers to question how to calculate distance by lat/lon and nothing for a "reverse" problem.
I have a displacment in X and Y and a GPS point (lat/lon), yet need to calc coordinates for a new point.
Using formula:
double deltaLat = dy / EARTH_RADIUS;
double deltaLon = dx / EARTH_RADIUS;
double lat = locLat + Math.signum(dy) * Math.toDegrees(deltaLat); // formula correct
double lon = locLon + Math.signum(dx) * Math.toDegrees(deltaLon);
It's accurate for calculating latitude, but for longitude I get about 10–15% error.
Does anyone have the same issue? Any possible formulas to calculate longitude by displacement?
The reason you're getting 10-15% error in longitude is because for longitude you cannot use the earth's radius to compute your displacement. Instead, you need to use the radius of the "circle" at the corresponding latitude. Therefore using your formula your longitude calculations should be more like
double deltaLon = dx / (EARTH_RADIUS * cos(locLat))
However this may give you undesired results around the poles, as cos(locLat) will get close to 0, so you may want to have some special cases for the poles (or even around them). Logically, if you think about, if you're at the pole, moving any distance along the x axis will not get your anywhere anyway.
Simplest but not the best solution is:
double deltaLat = dy / EARTH_RADIUS; // up-down
double deltaLon = dx / EARTH_RADIUS ; // left-right
double lat = locLat + Math.signum(dy) * Math.toDegrees(deltaLat); // formula correct
double lon = locLon + Math.signum(dx) * Math.toDegrees(deltaLon * 1.195);
I'm working on an Android app that uses Geopoints and I want to determinate a Geopoint from another Geopoint, a distance (in any format) and a polar angle. For example, I want to get coordinates of a place 100 meters in the North-North-East (22,5 degres) of my location got by the GPS in my phone.
The only method I've found is Location.distanceBetween(...).
Implementation for Android. This code is great for Unit Testing in your aplication:
public double radiansFromDegrees(double degrees)
{
return degrees * (Math.PI/180.0);
}
public double degreesFromRadians(double radians)
{
return radians * (180.0/Math.PI);
}
public Location locationFromLocation(Location fromLocation, double distance, double bearingDegrees)
{
double distanceKm = distance / 1000.0;
double distanceRadians = distanceKm / 6371.0;
//6,371 = Earth's radius in km
double bearingRadians = this.radiansFromDegrees(bearingDegrees);
double fromLatRadians = this.radiansFromDegrees(fromLocation.getLatitude());
double fromLonRadians = this.radiansFromDegrees(fromLocation.getLongitude());
double toLatRadians = Math.asin( Math.sin(fromLatRadians) * Math.cos(distanceRadians)
+ Math.cos(fromLatRadians) * Math.sin(distanceRadians) * Math.cos(bearingRadians) );
double toLonRadians = fromLonRadians + Math.atan2(Math.sin(bearingRadians)
* Math.sin(distanceRadians) * Math.cos(fromLatRadians), Math.cos(distanceRadians)
- Math.sin(fromLatRadians) * Math.sin(toLatRadians));
// adjust toLonRadians to be in the range -180 to +180...
toLonRadians = ((toLonRadians + 3*Math.PI) % (2*Math.PI) ) - Math.PI;
Location result = new Location(LocationManager.GPS_PROVIDER);
result.setLatitude(this.degreesFromRadians(toLatRadians));
result.setLongitude(this.degreesFromRadians(toLonRadians));
return result;
}
Take a look at great-circle formulas: http://en.wikipedia.org/wiki/Great-circle_distance
This should give You some hints on how to calculate the distances.
For a point in a given distance and heading, check http://williams.best.vwh.net/avform.htm#LL
Those formulas look quite complicated, but are easy to implement ;)