【问题标题】:How to Sort Geo-points according to the distance from current location in Android如何在Android中根据与当前位置的距离对地理点进行排序
【发布时间】:2015-06-25 01:03:41
【问题描述】:

我有一个“Place”对象,每个对象都有一个 LatLng 坐标:

import com.google.android.gms.maps.model.LatLng;

public class Place{
    public String name;
    public LatLng latlng;

    public Restaurant(String name, LatLng latlng) {
        this.name = name;
        this.latlng = latlng;
    }
}

我有一个包含这些地方的 ArrayList,如下所示:

    ArrayList<Place> places = new ArrayList<Place>();
    places.add("Place 1", LatLng(90.0,90.0));
    places.add("Place 2", LatLng(93.0,93.0));
    places.add("Place 3", LatLng(83.0,92.0));
    places.add("Place 4", LatLng(93.0,91.0));

我有“我的”LatLng:

    LatLng myLocation = new LatLng(10.0,10.0);

如何根据离我最近的对象对这些对象进行排序?感谢您的帮助

【问题讨论】:

  • 您熟悉 Comparable 界面吗?
  • 我是,我用它来做一些简单的事情,比如比较整数,但是我不知道如何比较距离之类的东西——这需要先计算

标签: android geolocation latitude-longitude


【解决方案1】:

你可以使用

distanceInMeters = (loc1.distanceTo(loc2));

来自 google maps API,然后将结果添加到 TreeMap 中的 Key

【讨论】:

    【解决方案2】:

    得到当前位置后,可以通过计算行车距离(最适合餐厅等场所)进行排序,如下所示,

    1. 计算到每个物体的距离

      http://maps.googleapis.com/maps/api/directions/json?origin="+yourLat+","+yourLong+"&destination="+toLat+","+toLong+"&sensor=false&mode=DRIVING
      
    2. 计算完每个距离后,对这些距离应用一些简单的排序算法。

    【讨论】:

    • 你知道google maps API是通过公路还是直线来获取距离的?
    • 我认为它提供的不是直线路线
    • 我去看看,如果是路线,它会比直线更有用,再次感谢
    • 欢迎您,您肯定需要道路路线,因为直线距离只是提供两个地理点之间的差异,这在现实世界中是不可用的。
    【解决方案3】:

    从@shieldstroy 发布的问题中获取this answer 的算法,使用Great Circle Distance,我得到了这个例子。

    这里是Comparator

    public class SortPlaces implements Comparator<Place> {
        LatLng currentLoc;
    
        public SortPlaces(LatLng current){
            currentLoc = current;
        }
        @Override
        public int compare(final Place place1, final Place place2) {
            double lat1 = place1.latlng.latitude;
            double lon1 = place1.latlng.longitude;
            double lat2 = place2.latlng.latitude;
            double lon2 = place2.latlng.longitude;
    
            double distanceToPlace1 = distance(currentLoc.latitude, currentLoc.longitude, lat1, lon1);
            double distanceToPlace2 = distance(currentLoc.latitude, currentLoc.longitude, lat2, lon2);
            return (int) (distanceToPlace1 - distanceToPlace2);
        }
    
        public double distance(double fromLat, double fromLon, double toLat, double toLon) {
            double radius = 6378137;   // approximate Earth radius, *in meters*
            double deltaLat = toLat - fromLat;
            double deltaLon = toLon - fromLon;
            double angle = 2 * Math.asin( Math.sqrt(
                    Math.pow(Math.sin(deltaLat/2), 2) +
                            Math.cos(fromLat) * Math.cos(toLat) *
                                    Math.pow(Math.sin(deltaLon/2), 2) ) );
            return radius * angle;
        }
    }
    

    这是高级代码,我只是把它放在onCreate()

            //My location, San Francisco
            double lat = 37.77657;
            double lng = -122.417506;
            LatLng latLng = new LatLng(lat, lng);
    
            //set up list
            ArrayList<Place> places = new ArrayList<Place>();
    
            places.add(new Place("New York", new LatLng(40.571256,73.98369)));
            places.add(new Place("Colorado", new LatLng(39.260658,-105.101615)));
            places.add(new Place("Los Angeles", new LatLng(33.986816,118.473819)));
    
            for (Place p: places){
                Log.i("Places before sorting", "Place: " + p.name);
            }
    
            //sort the list, give the Comparator the current location
            Collections.sort(places, new SortPlaces(latLng));
    
            for (Place p: places){
                Log.i("Places after sorting", "Place: " + p.name);
            }
    

    这是日志输出:

    04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: New York
    04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: Colorado
    04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: Los Angeles
    04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: Los Angeles
    04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: Colorado
    04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: New York
    

    【讨论】:

    • 感谢您的帮助,我最终做到了
    • 如果您有 10k 个位置要按距离计算和排序怎么办?
    • @Beemo 使用 Google Play 服务和 distanceBetween 或 distanceTo 在比较器中运行以获得最佳效率。
    【解决方案4】:

    对于计算距离,有不同的方法可用。一个非常简单的方法是 Haversine 公式 (http://rosettacode.org/wiki/Haversine_formula#Java)。更准确的计算是文森蒂公式。如果这两个位置距离不远,Haversine 解就足够了。

    计算距离后,您只需使用比较器对数组进行排序,例如:

    Collections.sort(places, new Comparator<Place>() {
        public int compare(Place p1, Place p2) {
            return Double.compare(p1.getDistance(), p2.getDistance());
        }
    });
    

    【讨论】:

    • 如果您有 10k 个位置来计算和按距离排序怎么办?
    • @Beemo 在比较器中使用 Google Play 服务和 distanceBetween 或 distanceTo 函数以获得最佳效率。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-22
    • 2015-07-21
    • 2017-10-29
    • 2021-06-23
    • 2014-04-27
    • 1970-01-01
    相关资源
    最近更新 更多