Calculate Distance From points in an Array - android

I'm developing an Android app that tracks the users location. I have it running locally so my LatLng are getting stored in an array :
ArrayList<LatLng> points = new ArrayList<>();
In onLocationChanged it then uses this to draw a poly line, this all works perfect for me. I want to calculate the distance of the entire journey. Is there a way to do this using my array?

You could make a loop that go through your array and compute the distance between two consecutive points. Then add every distance computed to obtain the whole trip distance. This should look like this (in pseudo code) :
totalDistance;
for(points in listOfPoints){
nextPoint = listOfPoints.indexof(point + 1);
distance = computeDistance(point, nextPoint);
totalDistance.add(distance);
}

For calculation distance between location points, you need at least two points.
Calculation can be found here:
https://stackoverflow.com/a/365853/1537916

Related

How to re-draw a route after the origin location changes using Azure Maps in Android application

I am building an Android app that will render a map. Using the phone location and a specific destination, I need to display the route on the map, and re-draw the route when the user's phone is moving. Sorry for the long post, I am trying to make this as explicit as possible.
I have to use Azure Maps, and the user has to follow the original route, so I need to re-draw the route when the user is following it. Basically I just need to make the original route start from the phone location everytime the user moves.
I am getting the latitude and longitude of the phone every three seconds, and when the user picks a destination location, I am calling the Azure API for the route, which returns a JSON array that contains points(latitude and longitude) from origin to destination. I save these points in an ArrayList and draw the route using a LineString and a LineLayer. My problem is that I don't want to call the Azure Api for the route every three seconds or even everytime the phone moves, because the call is really slow, and it puts to much pressure on my backend server.
Considering that the JSON array is sorted from origin to destination, I tried to compute the absolute difference between the phone location and the points from the array, and save the point for which the difference is smaller than a threshold, because it's the closest point from the route to the phone actual location. Every three seconds I am computing this difference and save the point as the start from the new route, and re-draw the route. The code for the difference is this:
private void getStartIndices() {
//r_points is the ArrayList with the points from the route
if(r_points != null)
{
for (int i = 0; i < r_points.length() - 1; i++) {
try {
JSONObject point = r_points.getJSONObject(i);
if( abs(mCurrentLocation.getLongitude() - point.getDouble("longitude")) < 0.00001 && abs(mCurrentLocation.getLatitude() - point.getDouble("latitude")) < 0.00001 )
{
Log.e(TAG, i + " They both change");
returnable = i;
}
else{
if( abs(mCurrentLocation.getLongitude() - point.getDouble("longitude")) < 0.000004 )
{
Log.e(TAG,i + "The longitude is changing");
returnable = i;
}
else{
if(abs(mCurrentLocation.getLatitude() - point.getDouble("latitude")) < 0.000004 )
{
Log.e(TAG,i + " The latitude is changing");
returnable = i;
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
This works but not accurate enough and it has some really bad bugs that I can't solve.
My question is: Is there any better way to do this, I really need to make as few calls as possible and I also need to make this redraw as accurate as possible.
The standard way to accomplish this is to loop through each line segment (pair of points in the line) and calculate the nearest point on that segment from your point. Then as you go through, find which segment has the closest point. Here is an algorithm that does this: https://softwareengineering.stackexchange.com/questions/270655/efficient-method-for-finding-closest-point-to-a-line-segment-from-a-set-of-point
However, this algorithm is based on pixel coordinates. If you use longitude/latitude coordinates, there will be some inaccuracies since the latitude and longitude scales are different (they aren't a flat 2D coordinate system, but part of a spherical coordinate system). An easy way to handle this is to convert your positions to pixel coordinates using the built in mercatorPositionsToPixels method in the MapMath namespace of the Azure Maps Android SDK. This will convert the longitude/latitude positions into pixel coordinates base don the Mercator map projection, and will result in much higher accuracy calculations. The zoom level specifies the resolution. Set this to 22, and that should work always (unless you want to start getting into microscopic accuracy).
/**
* Converts an array of positions into an array of global Mercator pixel coordinates at a specified zoom level.
* #param positions Array of positions.
* #param zoom Zoom level.
* #returns Array of global Mercator pixels.
*/
public static Pixel[] mercatorPositionsToPixels(#NonNull Position[] positions, double zoom)
Convert all the points of your line using this method, and store those since it sounds like your base line isn't changing. Then on each GPS ping, convert the GPS position to a Mercator pixel and use that nearest point on line algorithm to find the nearest point out of all the line segments. This will give you a point that could be between other points, but is on the path which is likely much more inline with what you are looking for.
In terms of performance, unless your line has millions of points in it, these calculations will run really fast. I used the same algorithm in JavaScript at a much higher frequency and it runs fine.
Update: the calculated coordinate will be in pixel units, you will need to convert it back to a position using the mercatorPixelsToPositions method.

How to find the difference in meter between two geo points in maps?

What would be the best way to know the nearest place of the list against the current user location.
is there a way to calculate the difference between two geo points in maps?
You can get the distance between 2 points making 2 Location objects (one for each point) and calling the method distanceTo.
Example.
// Instantiate.
Location pointOne=new Location("");
Location pointTwo=new Location("");
// Configure.
pointOne.setLatitude(doubleValue);
pointOne.setLongitude(doubleValue);
pointTwo.setLatitude(doubleValue);
pointTwo.setLongitude(doubleValue);
// Calculate distance.
float distanceInMeters=pointOne.distanceTo(pointTwo);
And that's all.
By the way, watch your grammar for better readibility =)
Good luck.

Efficient algorithm to find which part of Polyline contains within another Polyline

I am trying to compare a Polyline - overview_polyline ruturned by Google Directions API with a set of already existing Polylines and see which part of the new polyline already contains within one of these polylines. For me polyline is a driving route representation, retrieved from Google Directions API. It is basically any route anywhere in the world. Thou for simplification we can always find routes, which belong to a concrete city or a country and compare only thise. Also, at the moment it may be at most 250kms long. Here is some example:
It doesn't matter which route is existing here and which is new. In any case I would like to get the result, that this routes are similar (ok, may be they are not 90% similar, but lets assume they are).
At the moment I am using brute forcing to compare new polyline one by one with an existing polyline. Before that I am splitting polylines into points using this algorithm and compare each point to see, if there is a match. I treat points to be the same if distance between this points is less then 100 meters.
If I found that there is already some polyline, which mostly covers new polyline, I stop processing.
It looks like this:
Polyline findExistingPolyline(Polyline[] polylines, Polyline polyline) {
LatLng[] polylinePoints = PolylineDecoder.toLatLng(polyline);
for (Polyline existing: polylines) {
LatLng[] existingPoints = PolylineDecoder.toLatLng(existing);
if (isMostlyCovered(existingPoints , polylinePoints)) {
return existing;
}
}
return null;
}
boolean isMostlyCovered(LatLng[] existingPoints, LatLng[] polylinePoints) {
int initialSize = polylinePoints.length;
for (LatLng point: polylinePoints) {
for (LatLng existingPoint: existingPoints) {
if (distanceBetween(existingPoint, point) <= 100) {
polylinePoints.remove();// I actually use iterator, here it is just demosnstration
}
}
}
// check how many points are left and decide if polyline is mostly covered
// if 90% of the points is removed - existing polylines covers new polyline
return (polylinePoints.length * 100 / initialSize) <= 10;
}
Obviously, this algorithm sucks (especially in its worst case, when there is no match for new polyline) as there are two many cycles and may be too many points to compare.
So, I was wondering, if there is more efficient approach to compare polylines with each other.
You seem to compare only the points of the polylines, not the lines in between. That means that a straight line and the same line with an additional center point won't match. Or am I missing something? (If my assumption is right, that's the weak point in your method, I think.)
The distance calculation you use involves ellipsoid trigonometry and probably is expensive. You don't need exact measures here, though, you just want to match two nodes. If you need to cover a well-known range that's not close to a pole, you could consider lat/lon as flat coordinates, maybe with a correction to the longitude.
boolean isWithin100m(LatLng a, LatLng b) {
double dy = (a.lat - b.lat) * R * pi / 180.0;
if (dy < -100 || dy > 100) return false;
double dmid = 0.5 * (a.lat + b.lat) * pi / 180.0;
double dx = (a.lng - b.lng) * R * pi / 180.0 / cos(dmid);
return dx*dx + dy*dy <= 10000.0;
}
Here, R is Earth's radius. That method should be faster than your exact solution. If the cosines of your northernmost and southernmost points are similar, you could even leave them out and just add a fixed avarage cosine as constant factor to the longitude.
Also, you decode your new polyline with every comparison. You could do that only once in findExistingPolyline and pass a LatLng[] to isMostlyCovered. If you can precalculate data for your existing polylines, storing them as LatLng[] would also help. Keeping the extreme latitudes and longitudes for each polyline and maybe a line length can help you to rule out obvious mismatches early on.
Maybe you should even go beyond that: Along with longitude and latitude, store Earth-Centered, Earth-fixed coordinates and keep them in a k-d Tree for easy closest-neighbour lookup. That's my bet for the best speedup of your algorithm, at the cost of extra data.
And it's probably better not to create a new list for each polyline and then delete from it but to keep the lists intact and keep a local "used" set which should be quicker to look up than deleting points.

how to find distance from polyline in android?

How to find distance from polyline in google map in android using map apiV2 ? I want to find distance when user start moving from one location to another .
I used the Calculate distance in meters when you know longitude and latitude in java but it takes distance between two lat-long not as per user
moves in map. Please help me if anyone knows how to find distance using polyline.
For finding distance from your polyline you can use PolyUtil class which contains one method distanceToLine .
implementation'com.google.maps.android:android-maps-utils:0.5+'
add this library in your build.gradle.
For more you can use Google map utility class
https://developers.google.com/maps/documentation/android-api/utility/
For this you need to use thread. In that at regular interval you should find the distance between current coordinates and last saved coordinate.
Raw code:
Coordinate current, last;
Distance D = 0;
while (true) {
wait(10000);
last = current;
current = getNewCordinate;
d = D + distFrom(current, last);
}
This logic will help.
Based on the answer given by Gevaria Purva I found a more appropriate method on PolyUtil named isLocationOnPath.
For the third parameter most likely you want to pass true.

Distance between a point and several locations

I am developing an application that shows the distance between the user and multiple locations (such as foursquare in the image below) on android, I am using eclipse and would like to know how to calculate the distance between various points. Thank you!
Image:
http://i.stack.imgur.com/rsWmO.jpg
There are probably many ways to get this done, here's an option.
You could use the distanceTo() method. If you want more than one distance, simply use a loop to repeat it until you've calculated the distances between all the Locations you have at hand.
If you're using Google Maps, you can use a Distance Matrix
https://developers.google.com/maps/documentation/distancematrix/
https://developers.google.com/maps/documentation/javascript/distancematrix
Here I am providing you some sample code for Distance calculation. I have done like this in my project. Here distanceTo() method will return you the distance in double.
private Location currentLocation, distanceLocation;
double distance = 0;
//set your current location
currentLocation.setLatitude(currentLat);
currentLocation.setLongitude(currentLong);
//set your destination location
distanceLocation = new Location("");
distanceLocation.setLatitude(destinatioLat);
distanceLocation.setLongitude(destinationLong);
distance = currentLocation.distanceTo(distanceLocation)/1000;
Same for more then one location you can use Array for storing distance. Its on you how you want to use it as per your requirement.
Hope this will help you.

Categories

Resources