Google Maps API - Update current location on map based on distance travelled - android

Let's say i have set a walking route on google maps API from point A to point B.
I start at point A (duh). How can i, or is it possible, to update current location on map given the distance walked? (I'm getting distance walked from Google fit SDK).
Example:
From point A to point B is 1.5Km (A route marked on google maps)
I have ran 450m
How do i update map current position based on that?
PS: I can't use GPS as the app i'm making does not show your real current location. It's a false location

ok it is possible but you need to have the bearing of your direction.
for this you need three things -
bearing of your movement from source to destination.
the source latlong.
the distance travelled.
if you have those 3 things then this is how you do it-
private LatLng getDestinationPoint (LatLng source,double brng, double dist){
dist = dist / 6371;
brng = Math.toRadians(brng);
double lat1 = Math.toRadians(source.latitude), lon1 = Math.toRadians(source.longitude);
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
double lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
Math.cos(lat1),
Math.cos(dist) - Math.sin(lat1) *
Math.sin(lat2));
if (Double.isNaN(lat2) || Double.isNaN(lon2)) {
return null;
}
return new LatLng(Math.toDegrees(lat2), Math.toDegrees(lon2));
}
use my code from above function and put the arguments to function and in return you will get the destination latlng .
let me know if it was helpful to you.
thank you

Related

Get Latitude Longitude after x kilometer on Google Map without destination?

I am creating an Android app which requires finding a coordinate on the same route after X kilometers.
I have two coordinates x1,y1 & x2,y2 on a road. Now, my requirement is to find coordinate x3,y3 after some 3 kilometers (i.e., coordinate after x2,y2 not between x1,y1 & x2,y2) on the same road.
How can this be achieved ?
If you know the bearing, you can calculate the destination coordinate.
Sample Code:
private LatLng getDestinationPoint(LatLng source, double brng, double dist) {
dist = dist / 6371;
brng = Math.toRadians(brng);
double lat1 = Math.toRadians(source.latitude), lon1 = Math.toRadians(source.longitude);
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
double lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
Math.cos(lat1),
Math.cos(dist) - Math.sin(lat1) *
Math.sin(lat2));
if (Double.isNaN(lat2) || Double.isNaN(lon2)) {
return null;
}
return new LatLng(Math.toDegrees(lat2), Math.toDegrees(lon2));
}
Sample usage:
double radiusInKM = 10.0;
double bearing = 90;
LatLng destinationPoint = getDestinationPoint(new LatLng((25.48, -71.26), bearing, radiusInKM);
Or you can use heading between your pointA and pointB instead of bearing:
LatLng destinationPoint = getDestinationPoint(new LatLng(37.4038194,-122.081267), SphericalUtil.computeHeading(new LatLng(37.7577,-122.4376), new LatLng(37.4038194,-122.081267)), radiusInKM);
The SphericalUtil.computeHeading(p1, p2); method is from the Android Google Maps Utility library.
This is based on the Javascript method from this Stackoverflow answer.
If you want the point on same road, you might checkout this PHP answer.

Android alternative to iOS Google Maps API GMSGeometryOffset

I am working on an Android version of an Ios app I have developed and are running into problems with differences in the Google Maps API on the two platforms. In Ios I can use the method: GMSGeometryOffset. However, it is not present in the Android API. Therefore, I am looking for an alternative to this method so that I can calculate a new location based on the current location, a direction/bearing and a distance/radius.
I am using it to Draw a round circle while avoiding the egg shape. My code so far looks like the following. However, it gives me an egg shape unless the current location is directly on top of equator.
for(double angle = 0; angle < 2*Math.PI; angle = angle+ Math.PI/resolutionCircle)
{
latitude = position.latitude + (radiusCircle * Math.sin(angle));
longitude = position.longitude + (radiusCircle * Math.cos(angle));
inner.add(new LatLng(latitude, longitude));
}
There is a computeOffset method in the Google Maps Android API Utility Library.
It is a static method:
public static LatLng computeOffset(LatLng from,
double distance,
double heading)
It returns the LatLng resulting from moving a distance from an origin in the specified heading (expressed in degrees clockwise from north).
You can refer this documentation for more detail about Google Maps Android API Utility Library.
Google Maps' GitHub page also provide its detail implementation:
public static LatLng computeOffset(LatLng from, double distance, double heading) {
distance /= EARTH_RADIUS;
heading = toRadians(heading);
// http://williams.best.vwh.net/avform.htm#LL
double fromLat = toRadians(from.latitude);
double fromLng = toRadians(from.longitude);
double cosDistance = cos(distance);
double sinDistance = sin(distance);
double sinFromLat = sin(fromLat);
double cosFromLat = cos(fromLat);
double sinLat = cosDistance * sinFromLat + sinDistance * cosFromLat * cos(heading);
double dLng = atan2(
sinDistance * cosFromLat * sin(heading),
cosDistance - sinFromLat * sinLat);
return new LatLng(toDegrees(asin(sinLat)), toDegrees(fromLng + dLng));
}

Calculating distance travelled as the user moves

I need to calculate distance as the user moves in android. I have the starting point coordinates and can get the user's current location. How should I calculate distance.
I don't think I can call GoogleDistance Api as my application would be a real time application and calling this API would be extremely overhead or should calling GoogleDirectionsAPI would work fine.
Also I would like to test the distance travelled. How should I do it? Is there some way of sampling the data or do I really need to go out in the real world and actually travel and then test my application?
Edited: I want the distance travelled by the user and not the straight line distance between the points
I hope following will help:
In my app i started collecting lat longs after every 3fts (I set 3ft just for testing). I collected lat longs as follows:
Now I started calculating distance from point 1 to 2 and then 2 to 3 and then 3 to 4 and so on. After summing up I got total distance from 1 to 5.
I used following functions to calculate distance:
public double GetDistanceFromLatLonInKm(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);
}
This method is calculating exact distance for me.
You can calculate the distance between two point using the following function
double distanceBetweenTwoPoint(double srcLat, double srcLng, double desLat, double desLng) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(desLat - srcLat);
double dLng = Math.toRadians(desLng - srcLng);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(srcLat))
* Math.cos(Math.toRadians(desLat)) * Math.sin(dLng / 2)
* Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double dist = earthRadius * c;
double meterConversion = 1609;
return (int) (dist * meterConversion);
}
For the second Part: To use mock or sample data you can use "Fake GPS" app from the play store, which will generate mock location in your device.
Happy Coding
There are basically three ways to check the traveled distance -
By using GPS, check the coordinate between two points using distanceTo of Location class.
Using Accelerometer , you can check the movement of device using Accelerometer.
Using Step detector - this is recently updated by Android.
Hope this helps you to achieve your goal :)
For the first question . You have origin coordinates and the present user location coordinates so what you can do is google api v3 library provides a method that takes origin LatLng and destination LatLng and gives the distance . Add api v3 jar to your android build path.
For the second one goto google maps and give the location details it is accurate..

Using a GeoPoint location and meters X/Y, how can a Longitude/Latitude be calculated?

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);
}

Only Plotting Markers Within a Drawn Circle or Perimeter Google Maps v2 Android

Basically the title says it all. Rather than plotting every single entry in my database on a map as I do at the moment, I want to query the database and only plot the entries whose co-ordinates fall within the circle drawn around the users current location, however I can't quite figure out how to do it. At the moment, I have written code that plots the users current location on the map along with the locations of all the entries stored on my database and also the circle around the current location (See picture below). Based on my picture below, I only want the three markers within the circle to be plotted.
Does anyone know if there are any ways of checking if the latlng co-ordinates stored in my database fall within the area of the circle? Or if not, could anyone suggest any alternatives that use a similar idea.
An alternative I was thinking of was using a square / rectangle rather than a circle so that I could simply compare the co-ordinates of my entries with bounds of the square / rectangle, however I don't really know how feasible that is seen as those shapes aren't supported by the Google Maps API. I also came across the LatLngBounds class which could be useful but I can't find any sample code using it. How I might do this either?
I believe the circle has a fixed Radius and a center point.
So, go with this method to get the distance between the center and some LatLng and set a condition
distance <= radius
public static String getDistance(LatLng ll_source, LatLng ll_destination,
int unit) {
int Radius = 6371;// radius of earth in Km
double lat1 = ll_source.latitude;
double lat2 = ll_destination.latitude;
double lon1 = ll_source.longitude;
double lon2 = ll_destination.longitude;
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
* Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult = Radius * c;
double km = valueResult / 1;
DecimalFormat newFormat = new DecimalFormat("####");
Integer kmInDec = Integer.valueOf(newFormat.format(km));
double meter = valueResult % 1000;
Integer meterInDec = Integer.valueOf(newFormat.format(meter));
DecimalFormat df = new DecimalFormat("#.#");
return df.format(valueResult);
}
Ok, I've figured out a solution using the LatLngBounds class I referred to in my question. What it does is:
Creates a new rectangular perimeter around the user's current latitude and longitude co-ordinates (this example is roughly one square kilometer).
It then checks if the perimeter contains the co-ordinates stored in the database.
If it does, the marker is plotted on the map.
public void getNearbyMarkers(){
LatLngBounds perimeter = new LatLngBounds(new LatLng(currentLat - 0.004,
currentLon - 0.004), new LatLng(currentLat + 0.004, currentLon + 0.004));
if (perimeter.contains(LatlongFromDatabase)) {
//Plot Marker on Map
} else {
Toast.makeText(getApplicationContext(), "Co-ordinates not in perimeter!", 8).show();
}
}

Categories

Resources