如何计算地图中不同标记的距离,然后选择至少一个

Posted

技术标签:

【中文标题】如何计算地图中不同标记的距离,然后选择至少一个【英文标题】:How to calculate distance from different markers in a map and then pick up the least one 【发布时间】:2013-10-13 15:03:41 【问题描述】:

我必须从地图上的不同标记到设备当前位置的距离,然后选择最短的。我有标记的纬度和经度,并且可以动态获取当前位置的纬度和经度。

假设我在地图上有 5 个标记,班加罗尔 (Lat : 12.971599, Long : 77.594563), Delhi (Lat : 28.635308, Long : 77.224960), Mumbai (Lat : 19.075984, Long : 72.877656), Chennai (Lat : 13. ,长:80.250825),加尔各答(纬度:22.572646,长:88.363895)。

现在假设用户站在海得拉巴附近的某个地方(纬度:17.385044,经度:78.486671)。当用户单击按钮时,应用程序应计算与每个标记的距离并拾取并返回最短的标记,此处为班加罗尔。

有一种方法可以在本地数据库的帮助下完成。有人可以帮忙吗?

谁能给我一个很好的方法来做这个,或者如果你可以的话,想出一个好的代码。提前谢谢。

【问题讨论】:

您希望最多有多少个标记? 真正的应用程序有很多。大约 70-80.. 我已经回答过类似的问题。请查看此链接:***.com/questions/19332850/… 【参考方案1】:

从您的评论中,我看到您预计最多有 70-80 个位置。 这并不多。

您可以简单地对所有标记进行强力搜索并取最小值。

遍历所有标记,并搜索最小距离:

    List<Marker> markers = createMarkers(); // returns an ArrayList<Markers> from your data source
    int minIndex = -1;
    double minDist = 1E38; // initialize with a huge value that will be overwritten
    int size = markers.size();
    for (int i = 0; i < size; i++) 
        Marker marker = markers.get(i);
        double curDistance = calcDistance(curLatitude, curLongitude, marker.latitude, marker.longitude);
      if (curDistance < minDist) 
         minDist = curDistance;  // update neares
         minIndex = i;           // store index of nearest marker in minIndex
      
    

    if (minIndex >= 0) 
       // now nearest maker found:
       Marker nearestMarker = markers.get(minIndex);
       // TODO do something with nearesr marker
     else 
      // list of markers was empty
    

对于calcDistance,使用android提供的距离计算方法。 (例如Location.distanceTo()) 对于 70-80 个标记,无需使其更快和更复杂。 如果您有数千个点,那么值得投资于更快的解决方案(使用空间索引和避免 sqrt 计算的自己的距离计算)。

只需在最近的制造商搜索开始和结束时以毫秒为单位打印出当前时间,您就会发现它已经足够快了。

【讨论】:

非常感谢.. +1 的努力。我会试试这个,并在它执行后立即接受。不过还有一个疑问,“标记”在这里是一个数组吗? 但是如何将“地图上的标记”添加到这个数组列表中? 这是你的工作:添加一个元素,例如:(ArrayList markers = new ArrayList(); markers.add(new Marker(id, lat, lon);【参考方案2】:

如果您想找到最短的而不是列出最接近的并且您希望该过程扩展到大量位置,您可以在calculate distances之前进行一些过滤,您可以简化由于您不关心实际距离(即删除与地球半径的乘积),因此可以加快速度的公式。

过滤算法,循环遍历每个位置:

    计算纬度和经度的差异。 如果两个差异都大于先前处理的对,则丢弃它。 计算距离,保持最小。

您可以先向算法提供可能靠近的位置,从而进一步帮助算法。例如,如果您知道其中一个点位于同一国家或州。


这里有一些 Python 代码可以做到这一点,将其用作您的解决方案的伪代码:

locations =  
    'Bangalore' : (12.971599, 77.594563), 
    'Delhi' : (28.635308,  77.224960), 
    'Mumbai' : (19.075984,  72.877656), 
    'Chennai' : (13.052414,  80.250825), 
    'Kolkata' : (22.572646,  88.363895)
    

from math import sin, cos, atan2, sqrt

EARTH_RADIUS = 6373  # km

def distance(a, b):  # pass tuples
    (lat1, lon1) = a
    (lat2, lon2) = b
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = (sin(dlat/2))**2 + cos(lat1) * cos(lat2) * (sin(dlon/2))**2 
    c = 2 * atan2( sqrt(a), sqrt(1-a) ) 
    return EARTH_RADIUS * c


current = (17.385044, 78.486671)  # current lat & lng

closest = None
closest_name = None
for name, cordinates in locations.iteritems():
    d = distance(current, cordinates)
    if closest is None or d < closest:
        closest = d
        closest_name = name
    print "~%dkm (%s)" % (distance(current, cordinates), name)

print "\nClosest location is %s, %d km away." % (closest_name, closest)

输出:

~5700km (Kolkata)
~13219km (Chennai)
~12159km (Bangalore)
~7928km (Delhi)
~10921km (Mumbai)

Closest location is Kolkata, 5700 km away.

【讨论】:

你能用一个小代码给我建议吗?我试过但没有输出..请帮助.. @Akshat 查看代码,我发布了我还将发布过滤某些位置以使其扩展的算法。 @Emil.. 非常感谢.. 但我需要 Java 代码才能在 Android 中使用。虽然我会参考这个,但我会在明天首先尝试用 Java 生成代码。衷心感谢您以如此好的方式提供帮助.. :) :)【参考方案3】:

如何遍历所有标记并使用Location.distanceBetween 检查距离?没有魔法;)

List<Marker> markers;
LatLng currentPosition;

float minDistance = Float.MAX_VALUE;
Marker closest = null;
float[] currentDistance = new float[1];
for (Marker marker : markers) 
    LatLng markerPosition = marker.getPosition();
    Location.distanceBetween(currentPosition.latitude, currentPosition.longitude, markerPosition.latitude, markerPosition.longitude, currentDistance);
    if (minDistance > currentDistance[0]) 
        minDistance = currentDistance[0];
        closest = marker;
    

【讨论】:

【参考方案4】:

虽然已经发布了一些答案,但我想我会在 java 中展示我的实现。这已与包装在 AsyncTask 中的 4000 多个标记一起使用,并且一直在正常工作。

首先,计算距离的逻辑(假设您只有标记而不是 Location 对象,因为它们提供了执行 loc1.distanceTo(loc2) 的可能性):

private float distBetween(LatLng pos1, LatLng pos2) 
    return distBetween(pos1.latitude, pos1.longitude, pos2.latitude,
            pos2.longitude);


/** distance in meters **/
private float distBetween(double lat1, double lng1, double lat2, double lng2) 
    double earthRadius = 3958.75;
    double dLat = Math.toRadians(lat2 - lat1);
    double dLng = Math.toRadians(lng2 - lng1);
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(Math.toRadians(lat1))
            * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2)
            * Math.sin(dLng / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double dist = earthRadius * c;

    int meterConversion = 1609;

    return (float) (dist * meterConversion);

接下来,选择最近标记的代码:

private Marker getNearestMarker(List<Marker> markers,
        LatLng origin) 

    Marker nearestMarker = null;
    double lowestDistance = Double.MAX_VALUE;

    if (markers != null) 

        for (Marker marker : markers) 

            double dist = distBetween(origin, marker.getPosition());

            if (dist < lowestDistance) 
                nearestMarker = marker;
                lowestDistance = dist;
            
        
    

    return nearestMarker;

也许与您的用例无关,但我使用该算法根据预定义的距离选择最近的标记。这样我就清除了很多不必要的标记:

private List<Marker> getSurroundingMarkers(List<Marker> markers,
        LatLng origin, int maxDistanceMeters) 
    List<Marker> surroundingMarkers = null;

    if (markers != null) 
        surroundingMarkers = new ArrayList<Marker>();
        for (Marker marker : markers) 

            double dist = distBetween(origin, marker.getPosition());

            if (dist < maxDistanceMeters) 
                surroundingMarkers.add(marker);
            
        
    

    return surroundingMarkers;

希望对你有帮助

【讨论】:

getSurroundingMarkers:我不明白这个意思:您遍历所有标记并计算所有距离并将最近的标记保留在列表中。然后稍后要找到关闭,您需要再次计算周围的关闭。这是双重计算,没有任何收获 你的 distBetween 实现很奇怪。首先,您使用以米为单位的英里数作为地球半径,并在稍后将其转换为米。更好地以米为单位使用地球半径并避免最后一个meterConversion @AlexWien getSurroundingMarkers 单独使用。在我写的时候,这只是我用来获取一定距离内所有标记子集的东西。关于 distBetween 你可能是对的,尽管它有效并且转换对性能没有影响。【参考方案5】:

此代码可以帮助您获取距离:https://github.com/BeyondAR/beyondar/blob/master/android/BeyondAR_Framework/src/com/beyondar/android/util/math/Distance.java

【讨论】:

那么至少得到一个怎么样? 循环比较一下【参考方案6】:

这是我所谓的 KDTree 的实现,由 3 个类组成:KDTree、KDTNode 和 KDTResult。 您最终需要的是使用 KDTree.createTree() 创建 KDTree,它返回树的 rootNode 并获取传入的所有固定点。 然后使用 KDTree.findNearestWp() 找到离给定位置最近的 Waypoint。

KDTree:

public class KDTree 

private Comparator<LatLng> latComparator = new LatLonComparator(true);
private Comparator<LatLng> lonComparator = new LatLonComparator(false);;

/**
 * Create a KDTree from a list of Destinations. Returns the root-node of the
 * tree.
 */
public KDTNode createTree(List<LatLng> recList) 
    return createTreeRecursive(0, recList);


/**
 * Traverse the tree and find the nearest WP.
 * 
 * @param root
 * @param wp
 * @return
 */
static public LatLng findNearestWp(KDTNode root, LatLng wp) 
    KDTResult result = new KDTResult();
    findNearestWpRecursive(root, wp, result);
    return result.nearestDest;


private static void findNearestWpRecursive(KDTNode node, LatLng wp,
        KDTResult result) 
    double lat = wp.latitude;
    double lon = wp.longitude;
    /* If a leaf node, calculate distance and return. */
    if (node.isLeaf) 
        LatLng dest = node.wp;
        double latDiff = dest.latitude - lat;
        double lonDiff = dest.longitude - lon;
        double squareDist = latDiff * latDiff + lonDiff * lonDiff;
        // Replace a previously found nearestDest only if the new one is
        // nearer.
        if (result.nearestDest == null
                || result.squareDistance > squareDist) 
            result.nearestDest = dest;
            result.squareDistance = squareDist;
        
        return;
    
    boolean devidedByLat = node.depth % 2 == 0;
    boolean goLeft;
    /* Check whether left or right is more promising. */
    if (devidedByLat) 
        goLeft = lat < node.splitValue;
     else 
        goLeft = lon < node.splitValue;
    
    KDTNode child = goLeft ? node.left : node.right;
    findNearestWpRecursive(child, wp, result);
    /*
     * Check whether result needs to be checked also against the less
     * promising side.
     */
    if (result.squareDistance > node.minSquareDistance) 
        KDTNode otherChild = goLeft ? node.right : node.left;
        findNearestWpRecursive(otherChild, wp, result);
    



private KDTNode createTreeRecursive(int depth, List<LatLng> recList) 
    KDTNode node = new KDTNode();
    node.depth = depth;
    if (recList.size() == 1) 
        // Leafnode found
        node.isLeaf = true;
        node.wp = recList.get(0);
        return node;
    
    boolean divideByLat = node.depth % 2 == 0;
    sortRecListByDimension(recList, divideByLat);
    List<LatLng> leftList = getHalfOf(recList, true);
    List<LatLng> rightList = getHalfOf(recList, false);
    // Get split point and distance to last left and first right point.
    LatLng lastLeft = leftList.get(leftList.size() - 1);
    LatLng firstRight = rightList.get(0);
    double minDistanceToSplitValue;
    double splitValue;
    if (divideByLat) 
        minDistanceToSplitValue = (firstRight.latitude - lastLeft.latitude) / 2;
        splitValue = lastLeft.latitude + Math.abs(minDistanceToSplitValue);
     else 
        minDistanceToSplitValue = (firstRight.longitude - lastLeft.longitude) / 2;
        splitValue = lastLeft.longitude + Math.abs(minDistanceToSplitValue);
    
    node.splitValue = splitValue;
    node.minSquareDistance = minDistanceToSplitValue
            * minDistanceToSplitValue;
    /** Call next level */
    depth++;
    node.left = createTreeRecursive(depth, leftList);
    node.right = createTreeRecursive(depth, rightList);
    return node;


/**
 * Return a sublist representing the left or right half of a List. Size of
 * recList must be at least 2 !
 * 
 * IMPORTANT !!!!! Note: The original list must not be modified after
 * extracting this sublist, as the returned subList is still backed by the
 * original list.
 */
List<LatLng> getHalfOf(List<LatLng> recList, boolean leftHalf) 
    int mid = recList.size() / 2;
    if (leftHalf) 
        return recList.subList(0, mid);
     else 
        return recList.subList(mid, recList.size());
    


private void sortRecListByDimension(List<LatLng> recList, boolean sortByLat) 
    Comparator<LatLng> comparator = sortByLat ? latComparator
            : lonComparator;
    Collections.sort(recList, comparator);


class LatLonComparator implements Comparator<LatLng> 
    private boolean byLat;

    public LatLonComparator(boolean sortByLat) 
        this.byLat = sortByLat;
    

    @Override
    public int compare(LatLng lhs, LatLng rhs) 
        double diff;
        if (byLat) 
            diff = lhs.latitude - rhs.latitude;
         else 
            diff = lhs.longitude - rhs.longitude;
        
        if (diff > 0) 
            return 1;
         else if (diff < 0) 
            return -1;
         else 
            return 0;
        
    



KDT节点:

/** Node of the KDTree */
public class KDTNode 

KDTNode left;
KDTNode right;
boolean isLeaf;
/** latitude or longitude of the nodes division line. */
double splitValue;
/** Distance between division line and first point. */
double minSquareDistance;
/**
 * Depth of the node in the tree. An even depth devides the tree in the
 * latitude-axis, an odd depth devides the tree in the longitude-axis.
 */
int depth;
/** The Waypoint in case the node is a leaf node. */
LatLng wp;


KDT结果:

/** Holds the result of a tree traversal. */
public class KDTResult 
LatLng nearestDest;
// I use the square of the distance to avoid square-root operations.
double squareDistance;

请注意,我使用的是简化的距离计算,这适用于我的情况,因为我只对非常附近的航点感兴趣。对于相距较远的点,这可能会导致不完全是最近的点。两个经度的绝对差值表示为以米为单位的东西距离,取决于测量该差值的纬度。在我的算法中没有考虑到这一点,我不确定这种效果在你的情况下的相关性。

【讨论】:

非常感谢..我需要确定实现它。如果我得到任何问题,你会帮我吗? 我当然可以帮忙。但请注意我在最后一段中的(新)评论。与我的第一篇文章相比,我必须对其进行编辑。这有点太简单了。但我希望它仍然有帮助,如果航点的纬度差异不大,我认为它仍然可以很好地工作。您也可以在 SO 中搜索 KD-Tree,并找到一些关于处理球体坐标的讨论。 另见我的第二个答案,它实现了一个 3 维 KD-Tree 并将纬度/经度坐标转换为笛卡尔坐标系。【参考方案7】:

在二维中搜索单个点(可能经常变化)和大量点之间的最小距离的一种有效方法是使用QuadTree。最初构建 QuadTree 是有成本的(即,将标记位置添加到数据结构中),因此您只想执行一次(或尽可能不频繁地执行此操作)。但是,一旦构造完成,搜索最近点通常会比对大集合中的所有点进行蛮力比较要快。

BBN's OpenMap project has an open-source QuadTree Java implementation 我认为应该可以在具有get(float lat, float lon) 方法返回最近点的 Android 上运行。

Google 的 android-maps-utils 库也有 an open-source implementation of a QuadTree 打算在 Android 上运行,但目前它只支持 search(Bounds bounds) operation 来返回给定边界框中的一组点,而不是点最接近输入点。但是,可以对其进行修改以执行最近点搜索。

如果您的点数相对较少(70-80 可能足够小),那么在实际性能中,蛮力比较的执行时间可能与 QuadTree 解决方案相似。但是,这也取决于您打算重新计算最近点的频率 - 如果频繁,QuadTree 可能是更好的选择。

【讨论】:

【参考方案8】:

我认为将我的 KDTree(请参阅我的其他答案)也扩展到 3 维版本应该不会太难,这就是结果。 但由于我自己目前还没有使用这个版本,所以要小心。我添加了一个单元测试,这表明它至少适用于您的示例。

/** 3 dimensional implementation of a KDTree for LatLng coordinates. */
public class KDTree 

private XYZComparator xComparator = new XYZComparator(0);
private XYZComparator yComparator = new XYZComparator(1);
private XYZComparator zComparator = new XYZComparator(2);
private XYZComparator[] comparators =  xComparator, yComparator,
        zComparator ;

/**
 * Create a KDTree from a list of lat/lon coordinates. Returns the root-node
 * of the tree.
 */
public KDTNode createTree(List<LatLng> recList) 
    List<XYZ> xyzList = convertTo3Dimensions(recList);
    return createTreeRecursive(0, xyzList);


/**
 * Traverse the tree and find the point nearest to wp.
 */
static public LatLng findNearestWp(KDTNode root, LatLng wp) 
    KDTResult result = new KDTResult();
    XYZ xyz = convertTo3Dimensions(wp);
    findNearestWpRecursive(root, xyz, result);
    return result.nearestWp;


/** Convert lat/lon coordinates into a 3 dimensional xyz system. */
private static XYZ convertTo3Dimensions(LatLng wp) 
    // See e.g.
    // http://***.com/questions/8981943/lat-long-to-x-y-z-position-in-js-not-working
    double cosLat = Math.cos(wp.latitude * Math.PI / 180.0);
    double sinLat = Math.sin(wp.latitude * Math.PI / 180.0);
    double cosLon = Math.cos(wp.longitude * Math.PI / 180.0);
    double sinLon = Math.sin(wp.longitude * Math.PI / 180.0);
    double rad = 6378137.0;
    double f = 1.0 / 298.257224;
    double C = 1.0 / Math.sqrt(cosLat * cosLat + (1 - f) * (1 - f) * sinLat
            * sinLat);
    double S = (1.0 - f) * (1.0 - f) * C;
    XYZ result = new XYZ();
    result.x = (rad * C) * cosLat * cosLon;
    result.y = (rad * C) * cosLat * sinLon;
    result.z = (rad * S) * sinLat;
    result.wp = wp;
    return result;


private List<XYZ> convertTo3Dimensions(List<LatLng> recList) 
    List<XYZ> result = new ArrayList<KDTree.XYZ>();
    for (LatLng latLng : recList) 
        XYZ xyz = convertTo3Dimensions(latLng);
        result.add(xyz);
    
    return result;


private static void findNearestWpRecursive(KDTNode node, XYZ wp,
        KDTResult result) 
    /* If a leaf node, calculate distance and return. */
    if (node.isLeaf) 
        double xDiff = node.xyz.x - wp.x;
        double yDiff = node.xyz.y - wp.y;
        double zDiff = node.xyz.z - wp.z;
        double squareDist = xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
        // Replace a previously found nearestDest only if the new one is
        // nearer.
        if (result.nearestWp == null || result.squareDistance > squareDist) 
            result.nearestWp = node.xyz.wp;
            result.squareDistance = squareDist;
        
        return;
    
    int devidedByDimension = node.depth % 3;
    boolean goLeft;
    /* Check whether left or right is more promising. */
    if (devidedByDimension == 0) 
        goLeft = wp.x < node.splitValue;
     else if (devidedByDimension == 1) 
        goLeft = wp.y < node.splitValue;
     else 
        goLeft = wp.z < node.splitValue;
    
    KDTNode child = goLeft ? node.left : node.right;
    findNearestWpRecursive(child, wp, result);
    /*
     * Check whether result needs to be checked also against the less
     * promising side.
     */
    if (result.squareDistance > node.minSquareDistance) 
        KDTNode otherChild = goLeft ? node.right : node.left;
        findNearestWpRecursive(otherChild, wp, result);
    



private KDTNode createTreeRecursive(int depth, List<XYZ> recList) 
    KDTNode node = new KDTNode();
    node.depth = depth;
    if (recList.size() == 1) 
        // Leafnode found
        node.isLeaf = true;
        node.xyz = recList.get(0);
        return node;
    
    int dimension = node.depth % 3;
    sortWayPointListByDimension(recList, dimension);
    List<XYZ> leftList = getHalfOf(recList, true);
    List<XYZ> rightList = getHalfOf(recList, false);
    // Get split point and distance to last left and first right point.
    XYZ lastLeft = leftList.get(leftList.size() - 1);
    XYZ firstRight = rightList.get(0);
    double minDistanceToSplitValue;
    double splitValue;
    if (dimension == 0) 
        minDistanceToSplitValue = (firstRight.x - lastLeft.x) / 2;
        splitValue = lastLeft.x + Math.abs(minDistanceToSplitValue);
     else if (dimension == 1) 
        minDistanceToSplitValue = (firstRight.y - lastLeft.y) / 2;
        splitValue = lastLeft.y + Math.abs(minDistanceToSplitValue);
     else 
        minDistanceToSplitValue = (firstRight.z - lastLeft.z) / 2;
        splitValue = lastLeft.z + Math.abs(minDistanceToSplitValue);
    
    node.splitValue = splitValue;
    node.minSquareDistance = minDistanceToSplitValue
            * minDistanceToSplitValue;
    /** Call next level */
    depth++;
    node.left = createTreeRecursive(depth, leftList);
    node.right = createTreeRecursive(depth, rightList);
    return node;


/**
 * Return a sublist representing the left or right half of a List. Size of
 * recList must be at least 2 !
 * 
 * IMPORTANT !!!!! Note: The original list must not be modified after
 * extracting this sublist, as the returned subList is still backed by the
 * original list.
 */
List<XYZ> getHalfOf(List<XYZ> xyzList, boolean leftHalf) 
    int mid = xyzList.size() / 2;
    if (leftHalf) 
        return xyzList.subList(0, mid);
     else 
        return xyzList.subList(mid, xyzList.size());
    


private void sortWayPointListByDimension(List<XYZ> wayPointList, int sortBy) 
    XYZComparator comparator = comparators[sortBy];
    Collections.sort(wayPointList, comparator);


class XYZComparator implements Comparator<XYZ> 
    private int sortBy;

    public XYZComparator(int sortBy) 
        this.sortBy = sortBy;
    

    @Override
    public int compare(XYZ lhs, XYZ rhs) 
        double diff;
        if (sortBy == 0) 
            diff = lhs.x - rhs.x;
         else if (sortBy == 1) 
            diff = lhs.y - rhs.y;
         else 
            diff = lhs.z - rhs.z;
        
        if (diff > 0) 
            return 1;
         else if (diff < 0) 
            return -1;
         else 
            return 0;
        
    



/** 3 Dimensional coordinates of a waypoint. */
static class XYZ 
    double x;
    double y;
    double z;
    // Keep also the original waypoint
    LatLng wp;


/** Node of the KDTree */
public static class KDTNode 

    KDTNode left;
    KDTNode right;
    boolean isLeaf;
    /** latitude or longitude of the nodes division line. */
    double splitValue;
    /** Distance between division line and first point. */
    double minSquareDistance;
    /**
     * Depth of the node in the tree. Depth 0,3,6.. devides the tree in the
     * x-axis, depth 1,4,7,.. devides the tree in the y-axis and depth
     * 2,5,8... devides the tree in the z axis.
     */
    int depth;
    /** The Waypoint in case the node is a leaf node. */
    XYZ xyz;



/** Holds the result of a tree traversal. */
static class KDTResult 
    LatLng nearestWp;
    // We use the square of the distance to avoid square-root operations.
    double squareDistance;


这是单元测试:

public void testSOExample() 
    KDTree tree = new KDTree();
    LatLng Bangalore = new LatLng(12.971599, 77.594563);
    LatLng Delhi = new LatLng(28.635308, 77.224960);
    LatLng Mumbai = new LatLng(19.075984, 72.877656);
    LatLng Chennai = new LatLng(13.052414, 80.250825);
    LatLng Kolkata = new LatLng(22.572646, 88.363895);
    List<LatLng> cities = Arrays.asList(new LatLng[]  Bangalore, Delhi,
            Mumbai, Chennai, Kolkata );

    KDTree.KDTNode root = tree.createTree(cities);
    LatLng Hyderabad = new LatLng(17.385044, 78.486671);
    LatLng nearestWp = tree.findNearestWp(root, Hyderabad);

    assertEquals(nearestWp, Bangalore);

【讨论】:

【参考方案9】:

在这里,我有一种方法可以使用数据库。 这是一个计算距离函数:

public void calculateDistance() 

  if (latitude != 0.0 && longitude != 0.0) 
    for(int i=0;i<97;i++)  
      Location myTargetLocation=new Location("");
      myTargetLocation.setLatitude(targetLatitude[i]);
      myTargetLocation.setLongitude(targetLongitude[i]);
      distance[i]=myCurrentLocation.distanceTo(myTargetLocation);
      distance[i]=distance[i]/1000;
      mdb.insertDetails(name[i],targetLatitude[i], targetLongitude[i], distance[i]);
    

    Cursor c1= mdb.getallDetail();
    while (c1.moveToNext()) 
      String station_name=c1.getString(1);
      double latitude=c1.getDouble(2);
      double longitude=c1.getDouble(3);
      double dis=c1.getDouble(4);
      //Toast.makeText(getApplicationContext(),station_name+" & "+latitude+" &  "+longitude+" &  "+dis,1).show();
    
    Arrays.sort(distance);
    double nearest_distance=distance[0];
    Cursor c2=mdb.getNearestStationName();
    
        while (c2.moveToNext()) 

            double min_dis=c2.getDouble(4);
            if(min_dis==nearest_distance)
            
                String nearest_stationName=c2.getString(1);
                if(btn_clicked.equals("source"))
                
                source.setText(nearest_stationName);
                break;
                
                else if(btn_clicked.equals("dest"))
                
                    destination.setText(nearest_stationName);
                    break;
                
                else
                

                
            
        
    
     
     else
     
         Toast.makeText(this, "GPS is Not Working Properly,, please check Gps and  Wait for few second", 1).show(); 
     

我们所要做的就是创建一个名为 targetLatitude[i] 和 targetLongitude[i] 的数组,其中包含您要计算距离的所有地点的纬度和经度。 然后创建一个数据库,如下图:

public class MyDataBase 
    SQLiteDatabase sdb;
    MyHelper mh;
    MyDataBase(Context con)
    
    mh = new MyHelper(con, "Metro",null, 1);
    

public void open() 
try

sdb=mh.getWritableDatabase();

catch(Exception e)







public void insertDetails(String name,double latitude,double longitude,double distance) 

ContentValues cv=new ContentValues();
cv.put("name", name);
cv.put("latitude", latitude);
cv.put("longitude",longitude);
cv.put("distance", distance);
sdb.insert("stations", null, cv);


public void insertStops(String stop,double latitude,double logitude)

    ContentValues cv=new ContentValues();
    cv.put("stop", stop);
    cv.put("latitude", latitude);
    cv.put("logitude", logitude);
    sdb.insert("stops", null, cv);





public Cursor getallDetail()
   
    Cursor c=sdb.query("stations",null,null,null,null,null,null);
    return c;

public Cursor getNearestStationName() 
    Cursor c=sdb.query("stations",null,null,null,null,null,null);
    return c;



public Cursor getStops(String stop)

    Cursor c;
    c=sdb.query("stops",null,"stop=?",new String[]stop,null, null, null);
    return c;


class MyHelper extends SQLiteOpenHelper


    public MyHelper(Context context, String name, CursorFactory factory,
            int version) 
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
    

    @Override
    public void onCreate(SQLiteDatabase db) 
        // TODO Auto-generated method stub
        db.execSQL("Create table stations(_id integer primary key,name text," +
                " latitude double, longitude double, distance double );");
        db.execSQL("Create table stops(_id integer primary key,stop text," +
                "latitude double,logitude double);");

    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        // TODO Auto-generated method stub

    


public void deleteDetail() 
    sdb.delete("stations",null,null);
    sdb.delete("stops",null,null);



public void close() 
    sdb.close();




然后在任意位置执行CalculateDistance函数,即可得到最近的车站名称。

【讨论】:

以上是关于如何计算地图中不同标记的距离,然后选择至少一个的主要内容,如果未能解决你的问题,请参考以下文章

手机高德地图如何查两地距离

如何计算百度地图上两点的距离

地图上的两点怎样计算距离

百度地图如何测量两个地点的距离

谷歌距离地图,从给定地址/Lat,Lng 和自定义标记的最短路径,一个是默认选择当前位置,一个是自定义

如何在android中的谷歌地图上绘制路线并计算多个标记之间的距离