我可以少量调整Bing Map的View / LocationRect / Bounding Box吗?

时间:2014-11-14 19:22:13

标签: c# bing-maps pushpin

我正在使用此代码:

photraxMap.SetView(new LocationRect(App.photosetLocationCollection));

...缩放地图以显示photosetLocationCollection中包含的位置列表。

photraxMap 是BingMap。 SetView()是Bing Maps方法,而不是我自己的自定义方法。

问题在于它的工作太多 - 它显示所有标记/图钉,但只是勉强 - 极端位置被“剪裁”,如您所见:

enter image description here

在尖叫声中,您可以看到圣安地列斯以北的图钉以及地图东南边缘的哥伦比亚图钉被部分遮挡(Pardee的图钉也部分遮挡,按地图类型划分)盒子,但我认为无法帮助。)

我希望他们有一点“摆动空间”。这不仅仅是一个美容问题 - 在您向上或向下或向左或向右拖动地图之前,“异常值”图钉是不可选择的。

有没有办法调整缩放级别只是一个微不足道的比特(不是更高的完整缩放级别)?

更新

根据以下答案中的想法,我想我会尝试这样的事情:

// Adapted from Brundritt and Boonaert: http://stackoverflow.com/questions/26937358/can-i-adjust-my-bing-maps-view-locationrect-bounding-box-by-a-small-amount
// Before passing the locations to set view, call this twice, to add bogus NW and SE locations that will stretch 
// the viewable area of the map a little, like so:
// Location nwShim = GetAShimLocation(locs, true);
// Location seShim = GetAShimLocation(locs, false);
// locs.Add(nwShim); locs.Add(seShim);
public static Location GetAShimLocation(IList<Location> locations, bool IsForNorthwestCorner)
{
    const int MAP_CUSHION = 1; // Is 1 a comfortable enough cushion?
    // I don't know why the Lats are 85 instead of 90
    double maxLat = -85;
    double minLat = 85;
    double maxLon = -180;
    double minLon = 180;

    foreach (Location loc in locations)
    {
        if (loc.Latitude > maxLat)
        {
            maxLat = loc.Latitude;
        }

        if (loc.Latitude < minLat)
        {
            minLat = loc.Latitude;
        }

        if (loc.Longitude > maxLon)
        {
            maxLon = loc.Longitude;
        }

        if (loc.Longitude < minLon)
        {
            minLon = loc.Longitude;
        }
    }

    Location retLoc = new Location();
    // I'm not sure this logic/math is right - test it later
    if (IsForNorthwestCorner)
    {
        retLoc.Latitude = maxLat - MAP_CUSHION;
        retLoc.Longitude = maxLon - MAP_CUSHION;
    }
    else // SouthEast corner - stretch a little both directions
    {
        retLoc.Latitude = minLat + MAP_CUSHION;
        retLoc.Longitude = minLon + MAP_CUSHION;
    }
}

3 个答案:

答案 0 :(得分:2)

为了做到这一点,你至少有两个我想到的选择。

  • 第一个选项:使用虚假位置

您选择在最大/最小位置添加或检索的任意填充(纬度和经度的增量),然后使用SetView()设置图钉上的视图以及允许的其他添加位置超出缩放级别或正确设置视图以显示所有项目。

为了改进此技术,您可以根据图钉的像素大小和地图的分辨率计算地图的分辨率以及经度的纬度和增量的相应增量。

  • 第二个选项:手动计算最佳视图

对于第二个,我建议你阅读Ricky现在回忆的内容,亲眼看看:http://rbrundritt.wordpress.com/2009/07/21/determining-best-map-view-for-an-array-of-locations/

您需要适应的代码在这里(因为链接的答案不适合StackOverflow):

   /// <summary>
/// Calculates the best map view for a list of locations for a map
/// </summary>
/// <param name="locations">List of location objects</param>
/// <param name="mapWidth">Map width in pixels</param>
/// <param name="mapHeight">Map height in pixels</param>
/// <param name="buffer">Width in pixels to use to create a buffer around the map. This is to keep pushpins from being cut off on the edge</param>
/// <returns>Returns a MapViewSpecification with the best map center point and zoom level for the given set of locations</returns>
public static MapViewSpecification BestMapView(IList<Location> locations, double mapWidth, double mapHeight, int buffer)
{
    MapViewSpecification mapView;
    Location center = new Location();
    double zoomLevel = 0;

    double maxLat = -85;
    double minLat = 85;
    double maxLon = -180;
    double minLon = 180;

    //calculate bounding rectangle
    for (int i = 0; i < locations.Count; i++)
    {
        if (locations[i].Latitude > maxLat)
        {
            maxLat = locations[i].Latitude;
        }

        if (locations[i].Latitude < minLat)
        {
            minLat = locations[i].Latitude;
        }

        if (locations[i].Longitude > maxLon)
        {
            maxLon = locations[i].Longitude;
        }

        if (locations[i].Longitude < minLon)
        {
            minLon = locations[i].Longitude;
        }
    }

    center.Latitude = (maxLat + minLat) / 2;
    center.Longitude = (maxLon + minLon) / 2;

    double zoom1=0, zoom2=0;

    //Determine the best zoom level based on the map scale and bounding coordinate information
    if (maxLon != minLon && maxLat != minLat)
    {
        //best zoom level based on map width
        zoom1 = Math.Log(360.0 / 256.0 * (mapWidth – 2*buffer) / (maxLon – minLon)) / Math.Log(2);
        //best zoom level based on map height
        zoom2 = Math.Log(180.0 / 256.0 * (mapHeight – 2*buffer) / (maxLat – minLat)) / Math.Log(2);
    }

    //use the most zoomed out of the two zoom levels
    zoomLevel = (zoom1 < zoom2) ? zoom1 : zoom2;

    mapView = new MapViewSpecification(center, zoomLevel);

    return mapView;
}

如果您发现任何困难,请告诉我们,我们确信我们能够为您提供一些帮助。

  • 又一个帮助:

另外,我发现了一篇关于带有填充的最佳mapview的旧代码,我无法向你发送整个上下文,但你会得到这个想法:

//Determine the best zoom level based on the map scale and bounding coordinate information
if ((mapView.Bounds.SouthEast.Longitude != mapView.Bounds.NorthWest.Longitude) &&
    (mapView.Bounds.NorthWest.Latitude != mapView.Bounds.SouthEast.Latitude))
{
    Padding padding = mapView.Padding;

    //best zoom level based on map width
    zoom1 = (Math.Log(360.0 / 256.0 * (mapView.MapSize.Width - (padding.Left + padding.Right)) / (mapView.Bounds.SouthEast.Longitude - mapView.Bounds.NorthWest.Longitude)) / Math.Log(2));
    //best zoom level based on map height
    zoom2 = Math.Log(180.0 / 256.0 * (mapView.MapSize.Height - (padding.Top + padding.Bottom)) / (mapView.Bounds.NorthWest.Latitude - mapView.Bounds.SouthEast.Latitude)) / Math.Log(2);
}

//use the most zoomed out of the two zoom levels
mapView.ZoomLevel = (int)Math.Floor((zoom1 < zoom2) ? zoom1 : zoom2);

答案 1 :(得分:1)

更简单的解决方案是在使用Maps.setview后缩放maps.zoomlevel

bingMap.SetView(New LocationRect(locList))
bingMap.ZoomLevel = bingMap.ZoomLevel * 0.85
<。> .85表示缩小15%

P.S。我正在使用vb.net btw,但它是相同的概念

答案 2 :(得分:1)

您可以使用一系列用于创建图钉的位置,并将它们传递到 Microsoft.Maps.LocationRect 类的fromLocations函数中。此函数将返回一个 LocationRect ,其中包含传递给它的所有Location对象。然后,在设置地图视图时,可以将此 LocationRect 传递给bounds设置属性。一些开发人员可能会注意到,这导致某些图钉在地图边缘被切断。原因是 fromLocations 函数仅根据Location对象而不是图钉图标使用的其他区域来计算边界框。为了适应这种情况,可以使用padding设置将视图缓冲指定数量的像素。通常将此值设置为图钉图标的宽度/高度的两倍大即可。 source

var locs = [array of Microsoft.Maps.Location];
var rect = Microsoft.Maps.LocationRect.fromLocations(locs);

map.setView({ bounds: rect, padding: 80 });

等等! :)