How to round double values returned by Interface Location

Asked

Viewed 161 times

1

I own a ArrayList that stores GPS coordinate objects and their elements are always being compared with the double values returned by the methods getLatitude() and getLongitude() of Interface Location.

Problem

From the tests I’ve done I found it very difficult that the Smartphone user capture a GPS coordinate exactly like any of the elements of my ArrayList. So the solution I find for this problem, is to round up the values double of the objects of my ArrayList and also round the double values returned by the methods getLatitude() and getLongitude() of Interface Location, to be able to detect more successfully when the user is near the places I intend to control.

Can anyone tell me how best to round up the doubles returned by the methods getLatitude() and getLongitude() or indicate another solution to this problem?

Down below follows my ArrayList:

ArrayList<Coordenada> coordenadasPKs = new ArrayList<>();
    coordenadasPKs.add(new Coordenada(41.148185, -8.584755, 336.1));
    coordenadasPKs.add(new Coordenada(40.82614, -8.59654, 296));
    coordenadasPKs.add(new Coordenada(40.168235, -8.62813666666667, 199));
    coordenadasPKs.add(new Coordenada(39.69546, -8.50684666666667, 135));
    coordenadasPKs.add(new Coordenada(39.6148033333333, -8.49502833333333, 125));
    coordenadasPKs.add(new Coordenada(39.411415, -8.52799166666667, 99));
    coordenadasPKs.add(new Coordenada(39.1335366666667, -8.761665, 59));
  • Already tested how it keeps using Math.round() of life?

  • i had to do this once with php to generate a more "precise" google map in case I didn’t arredondei , I only limited the houses because the latitudo is compasta for seconds degrees in case I limited to minutes

  • calculates all distances by Italics and picks up the object that generated the smallest of them

  • @Gamen, the problem I find in the Math Class round() method, is that it makes a rounding to a very short and inaccurate value.

  • @J. William, could you give me an example of how to do this?

  • @Vitormendanha Cara, I don’t know if it’s the best way to do this, I actually think it’s the worst possible, but have you ever thought about doing a cast of the value in a String, format it to two decimal places, sla, as many as you like, and then convert to double again?

  • @Gamen, I have tried unsuccessfully to use the Class: Decimalformat numberFormat = new Decimalformat("#.000"), to round the Latitude and Longitude values of the Location object and the Arraylist objects. I hoped to find other solutions that were more precise...

  • 2

    Here is a Haversine Java implementation, which calculates distance between 2 coordinates: http://stackoverflow.com/questions/23776344/haversine-formula-in-java-producing-incorrectresult - you can use this to evaluate the user’s closest points.

Show 3 more comments

2 answers

2


Rounding up values may not be the best option.

What is normally used in this situation is the API Geofencingclient. It allows circular zones to be defined from a location and radius.

These zones are then monitored, and events are launched when the user enters or leaves this circle.

Giving a full explanation of how to use the API is something that would be too long for an answer.
You can find a tutorial here or consult Creating and Monitoring Geofences in the documentation.

Another option is to create Latlngbounds and check if the user’s location is inside it.

A Latlngbounds is a rectangle defined by the coordinates of its northeast and southwest corners.

You can create one from a coordinate and distance to the corners as follows:

//Calcula o ponto à distância 'raio' do 'centro*' na direção 45º(canto superior direito)
LatLng norhtEast = SphericalUtil.computeOffset(centro, raio, 45);

//Calcula o ponto à distância 'raio' do 'centro' na direção 225º(canto inferior esquerdo)
LatLng southWest = SphericalUtil.computeOffset(centro, raio, 225);

LatLngBounds bounds = new LatLngBounds(southWest,norhtEast);

Where

  • center - Latlng from the centre of the rectangle.
  • radius - Distance, in meters, from the center to the upper right(northeast) and lower left(southwest) corners of the Bounds

To check whether a Latlng is inside the Latlngbounds use:

boolean contains = bounds.contains(point); 

Edit, after your comment.

If you are not using the google maps api you do not have access to the class Latlngbounds.

Basically what you want is to know whether or not the user is near a particular location. To determine this you only need to define what "being close" is and a way to calculate the distance between two coordinates.

To calculate the distance should be used spherical trigonometry, usually we use the "haversine formula".

As Bacco said, there are several implementations on the net, the class Sphericalutil of lib com.google.maps.android:android-maps-utils and this mine class helper, are examples of this.

Add a method to your class Coordinated indicating, according to the criterion(x meters), if the coordinates passed as argument are close to the.

private boolean isNear(int criterio, double lat, double long){

    return GeoMath.getDistance(this.lat, this.long, lat, long) <= criterio;
}
  • ramaral, my app does not use Google Maps, as it does not need it for the role it is performing. Question: if I add in Gradle the line "Compile 'com.google.android.gms:play-services-maps:9.6.1'", so that through an Interface Location object I can create Latlng Class objects, I could create Latlngbounds objects ?

  • Yes, I think that would be enough, but I find it a little exaggerated if the intention is just to use the Latlngbounds class. A less "heavy" solution is to use the com.google.maps.android:android-maps-utils:0.4+ to calculate the distance between coordinates. See this reply.

  • Today I’m short on time, tomorrow I’ll complete the answer with an alternative to Bounds.

  • 2

    If it is to calculate distance in two pairs of strings (the user and the point of interest), Haversine is simple and fast. It has online mount implementations. Probably the libs mentioned in the reply use something like this internally.

  • @Bacco Yes it is true. A Sphericalutil that I refer uses Haversine. I myself have the mine "helper class".

  • @ramaral, I created in my project a Geomath Class like yours, but I’m not getting to import the Geopoint Class? I added in Gradle the line Compile 'com.google.maps.android:android-maps-utils:0.4+' and I still don’t see the option to import the Geopoint Class?

  • Eliminate the method public static double getDistance(GeoPoint point1, GeoPoint point2) of my class and use the public static double getDistance(double startLatitude, double startLongitude,&#xA; double endLatitude, double endLongitude)

  • There is another problem: It is not possible to add in Gradle the line 'com.google.maps.android:android-maps-utils:0.4+', because Android Studio shows errors in the file: C: Users Menda Androidstudioprojects Testes_gps_2 app build Intermediates manifests full debug Androidmanifest.xml

  • If you want to use my class you don’t need com.google.maps.android:android-maps-utils:0.4+

  • right, but your "class helper" class has Geopoint class objects that can’t care?

  • Also eliminate the getGeoPointAlongBearing. It is not necessary for distance calculation. Geopoint is a class of the old google maps api.

  • the "isNear" method, which he exemplified above, does not seem to be well discriminated ? Se eu criar um assim está correto: private boolean isNear(int criterio, double startLatitude, double startLongitude, double endLatitude, double endLongitude){&#xA;&#xA; return GeoMath.getDistance(startLatitude, startLongitude, endLatitude, endLongitude) <= criterio;&#xA; }

  • If the method is created in its Coordinates class, it already has the startLatitude, startLongitude, no need to pass them. That’s what I meant by this.lat, this.long

  • 1

    @ramaral, you are right in what I need to solve my problem, that is, the best solution will be to check if the user is close to any of the coordinates of the Arraylist coordinates. I will take your reply as accepted. Thank you.

Show 9 more comments

-1

As I suggested in the commentary:

int indice = 0;

// lat - latitude do cliente
// lon - longitude do cliente

double menorDistanciaAoQuadrado = Math.Pow(coordenadasPKs[i].getLatitude() - lat, 2) + Math.Pow(coordenadasPKs[i].getLongitude() - lon, 2);

double distanciaAoQuadrado;
for (int i = 1; i < coordenadasPKs.length; i++) {
    distanciaAoQuadrado = Math.Pow(coordenadasPKs[i].getLatitude() - lat, 2) + Math.Pow(coordenadasPKs[i].getLongitude() - lon, 2);
    if (distanciaAoQuadrado < menorDistanciaAoQuadrado) {
        menorDistanciaAoQuadrado = distanciaAoQuadrado;
        indice = i;
    }
}

The nearest point is coordenadasPKs[indice]. So I would solve this problem.

  • 3

    Remembering that Plants for calculation of geodesics only works for short distances, and away from the poles, If you do a thing like this to use in Argentina or North America, it is absurdly inaccurate. If you use in extreme places (such as pole transition or horizontal longitude "splicing"), you will fail. It would be better to use Haversine (not as precise as Vincenty, but it is very quick to calculate).

  • great point, Bacco

  • 1

    Note that I do not think simply wrong the solution, I just think it deserves a small observation in the answer in this sense, so that the user, when choosing the technique used, has notion of the limitations (I confess that I myself used this for a very specific situation, in a limited area of a city of the region, before implementing Haversine. But after haversine I was a little more quiet). https://en.wikipedia.org/wiki/Haversine_formula

Browser other questions tagged

You are not signed in. Login or sign up in order to post.