/* Montréal Just in Case Copyright (C) 2011 Mudar Noufal <mn@mudar.ca> Geographic locations of public safety services. A Montréal Open Data project. This file is part of Montréal Just in Case. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package ca.mudar.mtlaucasou.util; import android.content.Context; import android.content.res.Resources; import android.location.Address; import android.location.Geocoder; import android.location.Location; import android.os.Bundle; import android.support.annotation.Nullable; import com.google.android.gms.maps.model.LatLng; import java.io.IOException; import java.util.List; import ca.mudar.mtlaucasou.Const; import ca.mudar.mtlaucasou.R; import ca.mudar.mtlaucasou.data.UserPrefs; import static ca.mudar.mtlaucasou.util.LogUtils.makeLogTag; public class GeoUtils { private static final String TAG = makeLogTag("GeoUtils"); public static Location findLocationByName(Context context, String name) throws IOException { final List<Address> results = new Geocoder(context).getFromLocationName(name, 1, Const.MAPS_GEOCODER_LIMITS[0], Const.MAPS_GEOCODER_LIMITS[1], Const.MAPS_GEOCODER_LIMITS[2], Const.MAPS_GEOCODER_LIMITS[3]); if (!results.isEmpty()) { final Address address = results.get(0); if (((int) address.getLatitude() != 0) && ((int) address.getLongitude() != 0)) { final Location location = new Location(Const.CUSTOM_LOCATION_PROVIDER); location.setLatitude(address.getLatitude()); location.setLongitude(address.getLongitude()); final Bundle extras = new Bundle(); extras.putString(Const.BundleKeys.NAME, address.getFeatureName()); location.setExtras(extras); return location; } } return null; } public static float distanceBetween(LatLng position, LatLng destination) { float[] results = new float[3]; Location.distanceBetween(position.latitude, position.longitude, destination.latitude, destination.longitude, results); return results[0]; } @Nullable public static LatLng locationToLatLng(Location location) { if (location != null) { return new LatLng(location.getLatitude(), location.getLongitude()); } return null; } @Nullable public static Location positionToLocation(LatLng position) { if (position != null) { final Location location = new Location(Const.CUSTOM_LOCATION_PROVIDER); location.setLatitude(position.latitude); location.setLongitude(position.longitude); return location; } return null; } // public static LatLng locationToLatLng(@NonNull List<Double> coordinates) { // try { // return new LatLng(coordinates.get(1), coordinates.get(0)); // } catch (Exception e) { // e.printStackTrace(); // } // // return null; // } /** * Get distance in Metric or Imperial units. Display changes depending on * the value: different approximations in ft when > 1000. Very short * distances are not displayed to avoid problems with Location accuracy. * * @param context A Context * @param metricDistance The distance in Meters. * @return String Display the distance. */ public static String getDistanceDisplay(Context context, float metricDistance) { String sDistance; final String units = UserPrefs.getInstance(context).getUnitsSystem(); Resources res = context.getResources(); if (units.equals(Const.PrefsValues.UNITS_IMP)) { /** * Imperial units system, Miles and Feet. */ float fDistanceMi = metricDistance / Const.UnitsDisplay.METER_PER_MILE; if (fDistanceMi + (Const.UnitsDisplay.ACCURACY_FEET_FAR / Const.UnitsDisplay.FEET_PER_MILE) < 1) { /** * Display distance in Feet if less than one mile. */ int iDistanceFt = Math.round(fDistanceMi * Const.UnitsDisplay.FEET_PER_MILE); if (iDistanceFt <= Const.UnitsDisplay.MIN_FEET) { /** * Display "Less than 200 ft", which is +/- equal to the GPS * accuracy. */ sDistance = res.getString(R.string.placemark_distance_imp_min); } else { /** * When displaying in feet, we round up by 100 ft for * distances greater than 1000 ft and by 100 ft for smaller * distances. Example: 1243 ft becomes 1200 and 943 ft * becomes 940 ft. */ if (iDistanceFt > 1000) { iDistanceFt = Math.round(iDistanceFt / Const.UnitsDisplay.ACCURACY_FEET_FAR) * Const.UnitsDisplay.ACCURACY_FEET_FAR; } else { iDistanceFt = Math.round(iDistanceFt / Const.UnitsDisplay.ACCURACY_FEET_NEAR) * Const.UnitsDisplay.ACCURACY_FEET_NEAR; } sDistance = String.format(res.getString(R.string.placemark_distance_imp_feet), iDistanceFt); } } else { /** * Display distance in Miles when greater than 1 mile. */ sDistance = String.format(res.getString(R.string.placemark_distance_imp), fDistanceMi); } } else { /** * International Units system, Meters and Km. */ if (metricDistance <= Const.UnitsDisplay.MIN_METERS) { /** * Display "Less than 100 m". */ sDistance = res.getString(R.string.placemark_distance_iso_min); } else { /** * No need to have a constant for 1 Km = 1000 M */ float fDistanceKm = (metricDistance / 1000); sDistance = String .format(res.getString(R.string.placemark_distance_iso), fDistanceKm); } } return sDistance; } }