安卓:MapController.zoomToSpan:根据距离和中心点创建跨度

4

我已经在Google和SO上进行了研究,但我卡住了,我觉得我缺少了一些基本的东西。我看到的大多数示例都没有处理任意地图宽度和单个点,只有一个覆盖层的跨度。

我有一个地图点数据库、一个MapView和一个Geocoder。我可以在我的应用程序中搜索邮政编码,并由我的Geocoder返回一个Address

使用这个Address,我可以构建一个GeoPoint并搜索我的数据库,然后获得附近点的列表。问题在于尝试使用从返回的Address点和到数据库中最近点的距离构建的跨度进行缩放。

我只想让跨度包含最近的两个点(如果有)。这是相关的代码:

Collections.sort(listingDisplay, mComparator);
    listingDisplayAdapter.notifyDataSetChanged();

    float spanWidth =0;

    if (listingDisplay.size() > 1) {

        spanWidth = (float) (2 * distanceFromPoint(listingDisplay.get(1),
                current));

    } else if (listingDisplay.size() == 1) {

        spanWidth = (float) (2 * distanceFromPoint(listingDisplay.get(0),
                current));

    }

    Log.v(TAG, "SpanWidth: " + spanWidth);

    // Create span
    int minLat = (int) (current.getLatitudeE6() - (spanWidth * 1E6) / 2);
    int maxLat = (int) (current.getLatitudeE6() + (spanWidth * 1E6) / 2);
    int minLong = (int) (current.getLongitudeE6() - (spanWidth * 1E6) / 2);
    int maxLong = (int) (current.getLongitudeE6() + (spanWidth * 1E6) / 2);

        // Zoom against span. This appears to create a very small region that doesn't encompass the points
mapController.setCenter(current);
mapController.zoomToSpan(Math.abs( minLat - maxLat ), Math.abs( minLong - maxLong ));

ListingDisplay 包含了一组最接近的点,使用比较器 mComparator 对这个列表进行排序,将最接近我的返回地址(称为 currentGeoPoint)放在列表顶部。

然后,我根据最接近的点设置 spanWidth 的值,并尝试从中计算出跨度。

我的问题是,如何根据给定的距离和中心点构建一个跨度

1个回答

5

经过漫长的时间,我终于意识到我没有考虑一些重要信息,其中最主要的是Android上距离是使用WGS84椭球体来计算的。

最终,我使用了Jan Matuschek出色而简单的GeoLocation类中的辅助方法,该类非常详细地解释了涉及的概念。

我的方法基本上可以归结为以下内容。它可能可以大幅度优化,变成一个简单的SQL查询,但对于我的目的,它就是这样的,其中listingDisplay是从数据库检索的自定义LocationNode对象数组,而GeoPoint当前直接从标准Android Geocoder返回的Address创建。

public void setRegionForGeoPoint(GeoPoint current) {

    // Earth radius in KM
    final double EARTH_RADIUS = 6371.01;

    // Dummy span distance in KM for initial search; distance buffer is in M
    final double DISTANCE_BUFFER = 50;
    final double dummyDistance = 100.0;
//Create a list to store distances
    List<Double> distancesList = new ArrayList<Double>();


    // Loop through and modify LocationNodes with distance from user
    for (LocationNode location : listingDisplay) {
        location.setDistance((float) distanceFromUser(location));

        // Dynamically calculate distance from our current point (epicentre)
        distancesList.add(distanceFromPoint(location, current));
    }

    // Sort distances
    Collections.sort(distancesList);

    // Calculate regional span
    float spanWidth = (float) dummyDistance;
    double distance = 0;

    if (distancesList.size() > 0) {
        if (distancesList.size() > 1) {

            distance = distancesList.get(1);
            spanWidth = (float) (distance + DISTANCE_BUFFER);

        } else if (distancesList.size() == 1) {

            distance = distancesList.get(0);
            spanWidth = (float) (distance + DISTANCE_BUFFER);

        }

        //Obtain the spanwidth in metres.
        double spanWidthInKM = (double) spanWidth / 1000;

        // Create span
        GeoLocation[] boundingBoxSpan = currentGeoLocation
                .boundingCoordinates(spanWidthInKM, EARTH_RADIUS);

        //Create min/max values for final span calculation
        int minLatSpan = (int) (boundingBoxSpan[0].getLatitudeInDegrees() * 1E6);
        int maxLatSpan = (int) (boundingBoxSpan[1].getLatitudeInDegrees() * 1E6);
        int minLongSpan = (int) (boundingBoxSpan[0].getLongitudeInDegrees() * 1E6);
        int maxLongSpan = (int) (boundingBoxSpan[1].getLongitudeInDegrees() * 1E6);

        //Finally calculate span
        int latSpanE6 = Math.abs(minLatSpan - maxLatSpan);
        int lonSpanE6 = Math.abs(minLongSpan - maxLongSpan);

        // Set center
        mapController.setCenter(current);

        // Zoom to span
        mapController.zoomToSpan(latSpanE6, lonSpanE6);

    } else {

        //TODO: Handle the case when we have no distance values to use
    }
}


public double distanceFromPoint(LocationNode location, GeoPoint point) {

    // Calculate distance from user via result
    Location locationA = new Location("point A");
    locationA.setLatitude(location.getLatitude());
    locationA.setLongitude(location.getLongitude());

    Location locationB = new Location("point B");
    locationB.setLatitude((double) (point.getLatitudeE6() / 1E6));
    locationB.setLongitude((double) (point.getLongitudeE6() / 1E6));
    double distance = locationA.distanceTo(locationB);
    Log.v(TAG, "Calculated Distance: " + distance);
    return distance;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接