Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set correct Lat and Lng based on current location

My goal is to do autocomplete prediction using Google Places API, and now I want to make some kind algorithm that will take current location lat and lng, and make a prediction of places only in 100-200 km diameter.

So, at this moment I get user's current location lat and lng, how to set 100-200 km?

 private void getCurrentLocation() {
    mLastLocation = LocationServices.FusedLocationApi
            .getLastLocation(mGoogleApiClient);
    if (mLastLocation != null) {
        double latitude = mLastLocation.getLatitude();
        double longitude = mLastLocation.getLongitude();
        mLatLonBounds = new LatLngBounds(new LatLng(latitude,longitude),
                                  new LatLng(latitude,longitude));
        Log.d("myTag","lat = "+mLatLonBounds.northeast.latitude+" ,lon = "+mLatLonBounds.northeast.longitude);
        //Log.d("myTag","lat = "+mLatLonBounds.southwest.latitude+" ,lon = "+mLatLonBounds.southwest.longitude);

    }else {
        //some code
    }
}

Here is how I set bounds to auto prediction:

  @Nullable
private ArrayList<AutoCompletePlace> getAutocomplete(CharSequence constraint) {
    if (mGoogleApiClient.isConnected()) {
        Log.i(Constants.AUTO_COMPLETE_TAG, "Starting autocomplete query for: " + constraint);

        // Submit the query to the autocomplete API and retrieve a PendingResult that will
        // contain the results when the query completes.
        PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi
                        .getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
                                **mBounds**, mPlaceFilter);

        // This method should have been called off the main UI thread. Block and wait for at most 60s
        // for a result from the API.
        AutocompletePredictionBuffer autocompletePredictions = results.await(60, TimeUnit.SECONDS);

        // Confirm that the query completed successfully, otherwise return null
        final Status status = autocompletePredictions.getStatus();
        if (!status.isSuccess()) {
            Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
                    Toast.LENGTH_SHORT).show();
            Log.e(Constants.AUTO_COMPLETE_TAG, "Error getting autocomplete prediction API call: " + status.toString());
            autocompletePredictions.release();
            return null;
        }

        Log.i(Constants.AUTO_COMPLETE_TAG, "Query completed. Received " + autocompletePredictions.getCount()
                + " predictions.");

        // Copy the results into our own data structure, because we can't hold onto the buffer.
        // AutocompletePrediction objects encapsulate the API response (place ID and description).

        Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
        ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
        while (iterator.hasNext()) {
            AutocompletePrediction prediction = iterator.next();
            // Get the details of this prediction and copy it into a new PlaceAutocomplete object.
            resultList.add(new AutoCompletePlace(prediction.getPlaceId(),
                    prediction.getDescription()));
        }

        // Release the buffer now that all data has been copied.
        autocompletePredictions.release();

        return resultList;
    }
    Log.e(Constants.AUTO_COMPLETE_TAG, "Google API client is not connected for autocomplete query.");
    return null;

Example my current location 48.6180288,22.2984587.

UPDATE: Before the Francois Wouts give me the answer, I found another solution on stackoverflow, you can use it too.

 public static final LatLngBounds setBounds(Location location, int mDistanceInMeters ){
    double latRadian = Math.toRadians(location.getLatitude());
    double degLatKm = 110.574235;
    double degLongKm = 110.572833 * Math.cos(latRadian);
    double deltaLat = mDistanceInMeters / 1000.0 / degLatKm;
    double deltaLong = mDistanceInMeters / 1000.0 / degLongKm;

    double minLat = location.getLatitude() - deltaLat;
    double minLong = location.getLongitude() - deltaLong;
    double maxLat = location.getLatitude() + deltaLat;
    double maxLong = location.getLongitude() + deltaLong;

    Log.d("Location", "Min: " + Double.toString(minLat) + "," + Double.toString(minLong));
    Log.d("Location","Max: "+Double.toString(maxLat)+","+Double.toString(maxLong));

    // Set up the adapter that will retrieve suggestions from the Places Geo Data API that cover
    // the entire world.

    return new LatLngBounds(new LatLng(minLat,minLong),new LatLng(maxLat,maxLong));
like image 889
Dennis Zinkovski Avatar asked Sep 02 '15 11:09

Dennis Zinkovski


Video Answer


1 Answers

According to Wikipedia, you probably want to allow around 1 degree in each direction around the user's location to cover 100-200km. The exact area covered will depend on where the user is, but this should be a good enough approximation for most use cases.

Try the following, for example:

double radiusDegrees = 1.0;
LatLng center = /* the user's location */;
LatLng northEast = new LatLng(center.latitude + radiusDegrees, center.longitude + radiusDegrees);
LatLng southWest = new LatLng(center.latitude - radiusDegrees, center.longitude - radiusDegrees);
LatLngBounds bounds = LatLngBounds.builder()
        .include(northEast)
        .include(southWest)
        .build();

I believe this should work correctly even across the antemeridian. Let me know how you go!

like image 54
Francois Wouts Avatar answered Nov 15 '22 02:11

Francois Wouts