简体   繁体   English

当只有一个图钉时,如何确定 Bing 地图的正确缩放级别?

[英]How can I determine the correct zoom level for Bing Maps when there is only one pushpin?

I add a number of pushpins to a map and then "rightsize" or "right zoom" it so that all the pushpins show but so that the ones on the far edges are barely within the boundaries, like so:我在 map 中添加了一些图钉,然后“调整大小”或“右缩放”它,以便显示所有图钉,但远边缘上的图钉几乎不在边界内,如下所示:

在此处输入图像描述

However, if there is only one pushpin (as in the following case with Iowa, which only had the one civil war battle), rather than zero in on that as close as possible, it zooms out all the way to Skylab, like so:但是,如果只有一个图钉(如以下爱荷华州的案例,它只有一场内战),而不是尽可能接近零,它会一直缩小到 Skylab,如下所示:

在此处输入图像描述

This is the code I use to "right size" the map:这是我用来“正确调整”map 的代码:

private void RightsizeZoomLevelForAllPushpins()
{
    try
    {
        // Set the view so that all pushpins are displayed, with a bit of a margin around them
        // from https://stackoverflow.com/questions/65779504/how-to-set-the-zoom-level-of-bing-map-to-just-wide-enough-to-display-all-pushpin/65781319#65781319
        var map = this.userControl11.myMap;
        var locations = map.Children.OfType<Pushpin>().Select(x => x.Location);
        //Margin
        var w = new Pushpin().Width;
        var h = new Pushpin().Height;
        var margin = new Thickness(w / 2, h, w / 2, 0);

        //Set view
        map.SetView(locations, margin, 0);
        currentZoomLevel = Convert.ToInt32(map.ZoomLevel);
        UncheckAllZoomLevelToolstripMenuItems();
        SetZoomMenuItem();
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message);
    }
}

How can I get a one-pushpin map to not only center, but also zoom in as far as possible?如何让一键式 map 不仅居中,而且尽可能放大?

UPDATE更新

After adding parens to both references to Count, and adding an "if" in the else block so that it would compile, I still get two errors with this code:在对 Count 的两个引用添加括号,并在 else 块中添加一个“if”以便它可以编译之后,我仍然得到这个代码的两个错误:

private void RightsizeZoomLevelForAllPushpins()
{
    try
    {
        // Set the view so that all pushpins are displayed, with a bit of a margin around them
        var map = this.userControl11.myMap;
        var locations = map.Children.OfType<Pushpin>().Select(x => x.Location);

        if (locations.Count() == 1)
        {
            map.setView(locations[0], singlePinZoom);                
        }
        else if (locations.Count() > 1) 
        {
            //Margin
            var w = new Pushpin().Width;
            var h = new Pushpin().Height;
            var margin = new Thickness(w / 2, h, w / 2, 0);

            //Set view
            map.SetView(locations, margin, 0);
        }    
        currentZoomLevel = Convert.ToInt32(map.ZoomLevel);
        UncheckAllZoomLevelToolstripMenuItems();
        SetZoomMenuItem();
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message);
    }
}

They are:他们是:

1>C:\Users\bclay\source\repos\MyMaps\MyMaps\Form1.cs(155,33,155,45): error CS0021: Cannot apply indexing with [] to an expression of type 'IEnumerable<Location>'
1>C:\Users\bclay\source\repos\MyMaps\MyMaps\Form1.cs(155,25,155,32): error CS1061: 'Map' does not contain a definition for 'setView' and no accessible extension method 'setView' accepting a first argument of type 'Map' could be found (are you missing a using directive or an assembly reference?)

BTW, I'm not seeing any errors anymore in Visual Studio until I compile the project (it stopped finding errors as they were entered).顺便说一句,在我编译项目之前,我在 Visual Studio 中看不到任何错误(它在输入错误时停止发现错误)。 I don't know why... I changed no settings...我不知道为什么...我没有更改任何设置...

UPDATE 2更新 2

This is the code I'm using now, which does not take just one pushpin into account, but does work (note that "SetView" doesn't throw an exception here):这是我现在使用的代码,它不只考虑一个图钉,但确实有效(注意“SetView”在这里不会引发异常):

private void RightsizeZoomLevelForAllPushpins()
    {
        const int LEFT_TOP_RIGHT_MARGIN_ADDITION = 16;
        const int BOTTOM_MARGIN_ADDITION = 48;
        try
        {
            // Set the view so that all pushpins are displayed, with a bit of a margin around them
            // from https://stackoverflow.com/questions/65779504/how-to-set-the-zoom-level-of-bing-map-to-just-wide-enough-to-display-all-pushpin/65781319#65781319
            var map = this.userControl11.myMap;
            var locations = map.Children.OfType<Pushpin>().Select(x => x.Location);
            //Margin
            var w = new Pushpin().Width;
            var h = new Pushpin().Height;
            var margin = new Thickness((w / 2) + LEFT_TOP_RIGHT_MARGIN_ADDITION, 
                                        h + LEFT_TOP_RIGHT_MARGIN_ADDITION, 
                                        (w / 2) + LEFT_TOP_RIGHT_MARGIN_ADDITION, 
                                        0 + BOTTOM_MARGIN_ADDITION);
            //Set view
            map.SetView(locations, margin, 0);
            currentZoomLevel = Convert.ToInt32(map.ZoomLevel);
            UncheckAllZoomLevelToolstripMenuItems();
            SetZoomMenuItem();
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);
        }
    }

There is no single zoom level for a single pin, the best zoom level would depend on your scenario or what the pin is meant to represent, as well as the size of the map since both zoom and map size determine the viewable area.单个引脚没有单一的缩放级别,最佳缩放级别取决于您的场景或引脚的含义,以及 map 的大小,因为缩放和 map 大小决定了可视区域。 For example, if your pin represented a house you may want the map to be zoomed in more than if it represented a city.例如,如果您的图钉代表一座房子,您可能希望 map 比它代表一个城市时放大得更多。

That said, here is a modified version of your code that will handle the single pin scenario and use a static zoom level of your choosing:也就是说,这是您的代码的修改版本,它将处理单针场景并使用您选择的 static 缩放级别:

private double singlePinZoom = 15;

private void RightsizeZoomLevelForAllPushpins()
{
    try
    {
        // Set the view so that all pushpins are displayed, with a bit of a margin around them
        var map = this.userControl11.myMap;
        var locations = map.Children.OfType<Pushpin>().Select(x => x.Location);

        if(locations.Count() > 0) {
            //Margin
            var w = new Pushpin().Width;
            var h = new Pushpin().Height;
            var margin = new Thickness(w / 2, h, w / 2, 0);

            //Set view
            map.SetView(locations, margin, 0);
        } else(locations.Count == 1) {
            map.setView(locations[0], singlePinZoom);
        }   
        
        currentZoomLevel = Convert.ToInt32(map.ZoomLevel);
        UncheckAllZoomLevelToolstripMenuItems();
        SetZoomMenuItem();
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message);
    }
}

The answer in the other post shares the idea, but unfortunately is has(had) some syntax errors, and the logic of the if/else is wrong.另一篇文章中的答案分享了这个想法,但不幸的是有(有)一些语法错误,并且 if/else 的逻辑是错误的。 As I mentioned in the comments, these are some points to which you should pay attention:正如我在评论中提到的,这些是您应该注意的几点:

  1. locations in your code is IEnumerable<Location> and it doesn't have Count property, instead, you can use Count() extension method on it.您的代码中的locationsIEnumerable<Location>并且它没有Count属性,相反,您可以在其上使用Count()扩展方法。
  2. locations doesn't have indexer like arrays and you cannot use locations[0] to get the first element, instead you need to use locations.First() . locations没有像 arrays 这样的索引器,您不能使用locations[0]来获取第一个元素,而是需要使用locations.First()
  3. If you first check for Count()>0 , then Count()==1 will never hit.如果您首先检查Count()>0then Count()==1将永远不会命中。 So you need to change the conditions, for example first locations.Count() ==1 and then locations.Count() >1 .因此,您需要更改条件,例如首先locations.Count() ==1 ,然后是locations.Count() >1
  4. Make sure you add useing System.Linq;确保useing System.Linq; so you can use Count() and First() methods.所以你可以使用Count()First()方法。

Here is the modified version of your code:这是您的代码的修改版本:

private void RightsizeZoomLevelForAllPushpins()
{
    try
    {
        var map = this.userControl11.myMap;
        var locations = map.Children.OfType<Pushpin>().Select(x => x.Location);
        if(locations.Count()==1)
        {
            //Your preferred zoom level
            var zoomLevel = 12; 

            //Set view
            map.SetView(locations.First(), zoomLevel );
        }
        else if (locations.Count()>1)
        {
            //Margin
            var w = new Pushpin().Width;
            var h = new Pushpin().Height;
            var margin = new Thickness(w / 2, h, w / 2, 0);

            //Set view
            map.SetView(locations, margin, 0);
        }
        else
        {
            //Not necessary
            System.Windows.Forms.MessageBox.Show("No pushpin.");
        }
        currentZoomLevel = Convert.ToInt32(map.ZoomLevel);
        UncheckAllZoomLevelToolstripMenuItems();
        SetZoomMenuItem();
    }
    catch (Exception ex)
    {
        //Not necessary
        System.Windows.Forms.MessageBox.Show(ex.Message);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM