I am trying to calculate the distance between two locations (Current location with the previous location).
So I tried the following:
Location previousLocation = new Location("");
previousLocation.setLatitude(sharedPreferences.getFloat("previousLatitude", 0f));
previousLocation.setLongitude(sharedPreferences.getFloat("previousLongitude", 0f));
float distance = location.distanceTo(previousLocation);
totalDistanceInMeters += distance;
editor.putFloat("totalDistanceInMeters", totalDistanceInMeters);
Log.e("Location Update","totalDistance"+totalDistanceInMeters);
if (totalDistanceInMeters > 1)
{
Toast.makeText(getApplicationContext(), "Total UpdateLocation"+totalDistanceInMeters/1609, Toast.LENGTH_SHORT).show();
Log.e("Alert","Update");
}
To test the above code. The first time result was perfect and when it triggered the second time. The phone was in the same location but I am getting distances like 141.0111 m. thrid time 304.0011 m. Am I doing something wrong here?
The results are not showing up correctly. According to doc online the results are in metres.
Is there an easy way to calculate the difference between the first location results with the second one and if it is more than 10m I would like to do some other calculation if not just keep quite.
Let me know.
why are you even using the following code
float distance = location.distanceTo(previousLocation);
totalDistanceInMeters += distance;
That adds up the previous distance to present distance and gives the added value everytime....
example
first time
distance between A and B is 100 m
second time
distance between A and B is 100 m+100 m=200 m
so try using distance directly in toast
float distance = location.distanceTo(previousLocation);
if (totalDistanceInMeters > 1)
{
Toast.makeText(getApplicationContext(), "Total UpdateLocation"+distance/1609,Toast.LENGTH_SHORT).show();
Log.e("Alert","Update");
}
I think accuracy needs to be set in order to get the exact distance. Also try to get hold of the previous and current locations manually so as to calculate the distance and verify.
Related
I want to implement a touchListener on a polyline displayed with Google Maps V2 Android API.
Zoom level:
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(lat_Lng, 5);
I tried the following polyline touch code:
boolean onpoly = false;
for (Polyline polyline : mPolylines) {
for (LatLng polyCoords : polyline.getPoints()) {
float[] results = new float[1];
Location.distanceBetween(points.latitude, points.longitude, polyCoords.latitude, polyCoords.longitude, results);
if (results[0] < 100 ) {
onpoly = true;
Marker mark = map.addMarker(new MarkerOptions().position(points).title("AddEvent")
.snippet("" + addressaddexpense).icon(BitmapDescriptorFactory.fromResource(R.drawable.addicon)));
UtilsClass.dropPinEffect(mark);
}// end if..
} // end for loop
}// end for loop
if (onpoly == true) {
Toast.makeText(getActivity(), "Poly line detected", Toast.LENGTH_SHORT).show();
}// end if
It worked but not perfectly.
it will not detect the touch event unless i zoom in, sometimes forcing me to tap the map more than 5 times before zooming to achieve detection.
I then changed the aforementioned if condition from if (results[0] < 100 ) to if (results[0] < 150 * (22 - map.getCameraPosition().zoom)) and the functionality improved but it still does not work all the time.
Note: I want to detect polyline touch at any zoom level.
try this
final List<LatLng> latLngList; // Extract polyline coordinates and put them on this list
private GoogleMap map;
for(int i = 0; i < latLngList.size(); i++){
MarkerOptions mar = new MarkerOptions();
mar.position(new LatLng(latLngList.get(i).latitude, latLngList.get(i).longitude)).icon(BitmapDescriptorFactory.fromResource(R.drawable.trasparent_image)); //this image should be very small in size and transparent
map.addMarker(mar);
}
map.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker arg0) {
for(int i = 0; i < latLngList.size(); i++){
if(latLngList.get(i).latitude == arg0.getPosition().latitude && latLngList.get(i).longitude == arg0.getPosition().longitude){
Toast.makeText(MainActivity.this, "PolyLineClick ", Toast.LENGTH_SHORT).show();
break;
}
}
return false;
}
});
Until the questions in my comments are answered i thought i'll try to make them redundant by suggesting the usage of a 3rd party library; android-maps-utils
To do what i think you might be trying to do simply integrate the library and use the following line:
PolyUtil.isLocationOnPath(point, polyline.getPoints(), isGeodesic, tolerance);
For more information you can also look into this thread which seems applicable.
Goodluck.
I think your approach is correct. The only thing that fails is the distance check. And this is because os the touch and the zoom level:
You know that when you tap on the screen, the screen point that is passed to the applications is the center of your finger surface, that is in touch with the screen. This means, that even if it seems, that your finger is exactly over the PolyLine, it can be displaced with some pixels...
Now is time for the Zoom level, and depending in its current value, the distance between the point passed to the application and the PolyLine, can vary very much.
As a result, the if clause fails, and you have to tap several times, until some of your taps is near enough to the PolyLine. And of course it gets better with higher zoom level.
You should include the zoom level as you have done in you edited code, but with some extras: Check the "delta" that you will allow to enter the if, but on the max zoom level. It should be a small value. Then you have to just multiply it by the current zoom level, and calculate how this delta changes. Use this zoom dependant value in your if comparison.To enhance it, you can make a more complex calculation and get this delta, starting from pixel distance. Lets say, a tap that at 50px or less to the PolyLine will be accepted. Calculate this pixel distance in meters, again on the max zoom level and use it multiplied by the current zoom...To enhance it even more, you can get this pixel distance, to be dependant on the screen resolution and density.
Here, you can find how to calculate screen pixels to meters: https://stackoverflow.com/a/13635952/4776540
I implemented a similar thing in the following way:
Convert all locations to the screen coordinates using map.getProjection().toScreenLocation()
Use standard distance formula to determine distance from point to point (or from point to segment, if you want to detect clicks on line segments too) and if this distance is less than some threshold - click is detected.
The key point here is to use map projection to get screen coordinates. This way the decision depends on the real pixel distance on the screen, and does not depend on a zoom level.
I'm trying to make an app that points you toward a position. You press a button and it stores the gps coordinates, then calculates things like distance and the angle you need to face. Then it leads you back to that remembered position by "pointing" toward it using an onscreen compass graphic.
At least, it's supposed to. After messing with the code for hours, I've come to the conclusion that there's just a logic error somewhere due to my lack of trig practice over the past few years.
The compass and GPS position are updated fairly frequently. This is the code in my main update call for the user interface that rotates the compass and displays the distance.
public void updateUI(){
double deltaX = targetLongitude - currentLongitude;
double deltaY = targetLatitude - currentLatitude;
double distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
double rotation = Math.toDegrees(Math.atan2(deltaX,deltaY));
distanceTextView.setText(Double.toString(distance));
rotateCompass(rotation - degreesClockwiseFromNorth);
}
and the code for rotateCompass:
public void rotateCompass(double degrees){
degrees -= currentRotation; //calculates necessary rotation across updates
currentRotation += degrees;
matrix.postRotate(
(float) degrees,
compass.getDrawable().getBounds().width() / 2,
compass.getDrawable().getBounds().height() / 2);
compass.setImageMatrix(matrix);
}
I'm almost certain my rotation code works because when I replace
rotateCompass(rotation - degreesClockwiseFromNorth);
with
rotateCompass(0 - degreesClockwiseFromNorth);
it points north right alongside a real compass regardless of the direction I'm facing. But when I use the former, it points towards a consistent point, but that point seems to be nowhere near the target point.
So I've come to the conclusion my error is either in calculating the correct angle, or expecting the gps to be too precise. I haven't tested it for distances further than what I can in my backyard, but I assume that if it was a gps accuracy issue I'd see my compass jumping all over the place rather than adamantly pointing in a wrong direction.
Thanks for reading, any suggestions or corrections are appreciated.
Your math is all screwed up because the distance between 2 degrees of longitude is not the same as 2 degrees of latitude. In fact, it isn't even a constant length for longitude- its shorted by the poles and longest at the equator. Use the Location.distanceTo functions instead.
I am writing an application using phonegap to store an update lat/lon every 5 seconds to a mysql database. I would like to be able to allow my users to see the total distance traveled since starting the app.
I've taken a look at the Phonegap geolocation API and cannot see a way to calculate total distance traveled based upon lat / lon updates. Is there a way to accomplish this?
EDIT: # Drew thanks for the link. I have looked it over and the JS version of Haversine looks straight forward. the difficult part will be the way phonegap pulls and stores lat/lon. Currently my function to get and send the location to MySQL is
function geo_success(position) {
$("#status p").text("Tracking active");
$('#status').removeClass("stopped").addClass("active");
$('button').text("Stop tracking");
latlon.lat = position.coords.latitude;
latlon.lon = position.coords.longitude;
latlon.alt = position.coords.altitude;
if(!position.coords.speed) { latlon.speed = 0; }
else{ latlon.speed = position.coords.speed }
if(first) {
intervalId = setInterval(send, 5000);
}
first = false;
}
Is there a way you can think of to store the latest value for lat1 lon1 and use the previous for lat2 lon2 and cycle the newest incoming coordinates through those 2 sets of variables? That way i can take the returned variable d from the haversine and store it in the db (to be able to sum it up later). Many thanks.
You would have to create an algorithm yourself that take those coordinates every 5 seconds, do some algebra on them to determine the distance between the two, and add it to the total distance somewhere, then repeat for the next 5 seconds.
For the actual algorithm of calculating the distance, look at this answer.
First read Question carefully ...
I need straight distance, not by walking,car,or etc.
Take a look to this image which given below,
Google provide us distance by car and driving.
But I don't want it, I want straight distance between two location (latitude - longitude).
Which is displayed as as RED LINE.
NOTE : I don't want to put red line on Google map, just want the Distance in Units(mile,km,etc.)
ANDROID
double distance
Location locationA = new Location(“point A”)
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location(“point B”);
locationB.setLatitude(latB);
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB);
MATHEMATICALY
a = distance in degrees //meterConversion = 1609;
b = 90 - latitude of point 1
c = 90 - latitude of point 2
l = longitude of point 1 - longitude of point 2
Cos(a) = Cos(b)Cos(c) + Sin(b)Sin(c)Sin(l)
d = circumference of Earth * a / 360 // circumference of Earth = 3958.7558657440545D km
The Haversine function is used to find the distance between two points on a sphere.
It's fairly straightforward to extend this to finding the straight line distance between two points on the Earth. The Earth is not a perfect sphere, but this is still a good approximation using a standard measurement (called WGS84) for the radius at the equator.
As CommonsWare has said, you can do this very simply by using distanceBetween(), which uses the Haversine function and the WGS84 radius.
For better understanding of implementation/math, take a look at this sample code in Python.
Distance you find with following code.
You just need to get two geoPoint's latitude and longitude.
and use that in following calculation to get distance.
R = 6371; // km
d = Math.acos(Math.sin(lat1)*Math.sin(lat2) +
Math.cos(lat1)*Math.cos(lat2) *
Math.cos(lon2-lon1)) * R;
That will be return distance after all calculation.
R is the radius of surface in KM, need to use in calculation and you try this. I hope it is useful for you.
I'm trying to make a GPS Android app and am having trouble setting a destination point.
all the program does at the moment is grab your GPS location, and display your Latitude and Longitude, I want the app to tell you when you have reached a certain Latitude or Longitude but the coordinates don't stay at a steady number so I can never get the event to happen for more then a second before the coordinates change, I think I need the event to happen between two different coordinates, one being higher then the target coordinates and the other being lower but I can't figure out how to do that, someone please help
Specify a broader area that you'll accept.
if(lat > TARGET_LAT - 0.02 && lat < TARGET_LAT + 0.02 && lon > TARGET_LON - 0.02 && lon < TARGET_LON + 0.02){
// close enough!
}
See this for an idea on what the numbers should be.