【问题标题】:How do I add polyline length to a Bing Maps polygon如何将折线长度添加到 Bing 地图多边形
【发布时间】:2014-09-20 01:03:34
【问题描述】:

我正在尝试使用 Bing 地图在我的系统中重新创建税务地图。我的问题是列出我正在创建的多边形边的长度(以英尺为单位)。我很清楚如何从数据库中的 MSSQL 2012 几何或地理项目中获取我正在创建的折线的长度。我无法弄清楚如何有效地向用户展示它。对于如何做到这一点,我有两个想法。

  1. 将长度直接放在相关多段线上或附近。
  2. 在整个多边形上创建一个强调点,并在地图一侧列出基于顺时针顺序的多边形边长。

这两个选项中的任何一个都可以作为可接受的解决方案。我使用本教程创建了我当前的环境,因此我希望以某种方式将解决方案集成到其中: How to create a spatial web service that connects a database to Bing Maps using EF5 请注意,我的实现仅使用代码的国家/地区部分,因此我不需要处理该教程中的城市等单点。

可以在此处找到处理我需要编辑的地图绘制的相关代码: Bing Maps v7 WellKnowTextModule

【问题讨论】:

    标签: bing-maps polyline


    【解决方案1】:

    如果您想在 SQL2012 中获取多边形的周长,您可以获取它的外环。外环将是 LineString,即“@g.SExteriorRing()”。然后沿着那条线测量长度。即“@g.SExteriorRing().STLength()”。但是,国家通常不仅仅是单个多边形,它们可以是 MultiPpolygons 或 GeometryCollections。所以要计算这些长度,我们必须做更多的工作。这是一个帮助方法,您可以添加到服务中以计算这些形状的周长:

    private double CalculateLength(SqlGeometry geom)
    {
        double length = 0;
    
        if(string.Compare(geom.STGeometryType().Value, "polygon", true) == 0)
        {
    
        }
        else if (string.Compare(geom.STGeometryType().Value, "multipolygon", true) == 0)
        {
            int numPolygon = geom.STNumGeometries().Value;
            for(int i = 1; i <= numPolygon; i++){
                length += geom.STGeometryN(i).STExteriorRing().STLength().Value;
            }                
        }
        else if (string.Compare(geom.STGeometryType().Value, "geometrycollection", true) == 0)
        {
            int numGeom = geom.STNumGeometries().Value;
            for (int i = 1; i <= numGeom; i++)
            {
                length += CalculateLength(geom.STGeometryN(i));
            }
        }
    
        return length;
    }
    

    要从服务器端获取长度信息到客户端,请向 Country 或 BaseEntity 类添加一个属性,如下所示:

    [DataMember]
    public double Perimeter { get; set; }
    

    在使用 linq 查询获取响应结果后,您可以在此处填充此值,使用一个简单的循环调用之前的辅助方法:

    for (int i = 0; i < r.Results.Count;i++)
    {
        var geom = SqlGeometry.STGeomFromText(new System.Data.SqlTypes.SqlChars(r.Results[i].WKT), 4326);
        r.Results[i].Perimeter = CalculateLength(geom);
    }
    

    关于在地图上显示信息。将信息放置在折线上的一种简单方法是选择沿线的坐标,也许是中间的坐标,只需获取线中的 # 或坐标并找到中间索引并将该坐标用作图钉。然后,您可以使用带有文本的背景图像或使用自定义 HTML 创建自定义推送:

    http://www.bingmapsportal.com/ISDK/AjaxV7#Pushpins4

    http://www.bingmapsportal.com/ISDK/AjaxV7#Pushpins15

    【讨论】:

    • 我最终使用 html 标签来标记距离。它在个位数缩放级别占用太多空间存在一些问题,但切换按钮应该可以解决这个问题。谢谢。
    【解决方案2】:

    想在我接受的答案中添加一个附录,因为我觉得它改变了一点。

    在处理这个问题时,我发现我实际上无法通过实体框架获得每个线段的长度。这是因为查询需要将我的地理更改回几何,然后将其解析为其基线段,然后将这些线段更改回地理。查询,即使在 SQL 中,也需要几分钟,所以它不是在 EF 中动态运行的选项。

    我最终在我的数据库中创建了另一个表,其中包含我拥有的每个多边形的每一侧的已解析线段。然后我可以将线段的质心用作人造城市。然后,我在方法中的 for 循环之后从问题中提到的教程中将此逻辑添加到 DisplayData javascript 函数中。

    if (shape.getLength) {
      } else {
        var chkPolygon = data.Results[0].WKT.substring(0, data.Results[0].WKT.indexOf('(', 0));
        chkPolygon = chkPolygon.replace(/\s/g, '');
    
        switch (chkPolygon.toLowerCase()) {
          case 'point':
    
          case 'polygon':
            var latlonCheck = map.getCenter();
            var setSides = window.location.origin + "/SpatialService.svc/FindNearBy?latitude=" +
              latlonCheck.latitude + "&longitude=" + latlonCheck.longitude +
              "&radius=" + data.Results[0].ID + "&layerName=" + "city" + "&callback=?";
    
            CallRESTService(setSides, DisplaySides);
          default:
            break;
        }
      }
    

    data.Results[0].ID 将在该特定国家/地区的新表中查找所有线段。然后使用 DisplaySides 函数将 html 图钉作为“城市”覆盖在地图上每一侧的适当点上

    function DisplaySides(getSides) {
      infobox.setOptions({ visible: false });
      if (getSides && getSides.Results != null) {
        for (var i = 0; i < getSides.Results.length; i++) {
          var sideLenFtShort = Math.round(getSides.Results[i].LengthFeet * 100) / 100;
          var htmlLenString = "<div style='font-size:14px;border:thin solid black;background-color:white;font-weight:bold;color:black;'>" + sideLenFtShort.toString(); + "</div>";
          var testString = {
            pushpinOptions: { width: null, height: null, htmlContent: htmlLenString }
          };
          var sideCtr = WKTModule.Read(getSides.Results[i].WKT, testString);
    
          dataLayer.push(sideCtr);
        }
      }
      else if (getSides && getSides.Error != null) {
        alert("Error: " + getSides.Error);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-06-16
      • 2020-02-17
      • 2012-06-12
      • 2019-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      相关资源
      最近更新 更多