【问题标题】:Google maps - how to get building's polygon coordinates from address?谷歌地图 - 如何从地址获取建筑物的多边形坐标?
【发布时间】:2023-03-04 23:46:01
【问题描述】:

如何实现以下:

  1. 用户定义地址
  2. 用户定义颜色
  3. 服务在谷歌地图上搜索相应的建筑
  4. 服务用颜色填充地图上找到的建筑物

我知道如何:

1.查找地址的经纬度

2.绘制多边形

所以,要完成任务,我需要从地址获取建筑物的多边形坐标。怎么做?

【问题讨论】:

    标签: google-maps geolocation geocoding


    【解决方案1】:

    (1)Acquire image tile

    (2) 根据像素颜色(此处为 0xF2EEE6)分割建筑物。

    (3) 图像清理(例如erosion then dilation)+ 获取多边形角点像素坐标的算法。

    (4)Mercator projection to acquire lat/long of pixel

    【讨论】:

      【解决方案2】:

      您可以使用 Google Geocoding API 将地址转换为地理坐标。

      https://maps.googleapis.com/maps/api/geocode/json?address=SOME_ADDRESS&key=YOUR_API_KEY
      

      然后,您可以使用 Python 和样式化的静态地图在某个位置获取建筑物的多边形(以像素坐标表示):

      import numpy as np
      from requests.utils import quote
      from skimage.measure import find_contours, points_in_poly, approximate_polygon
      from skimage import io
      from skimage import color
      from threading import Thread
      
      center_latitude = None ##put latitude here 
      center_longitude = None ##put longitude here 
      mapZoom = str(20)
      midX = 300
      midY = 300
      # Styled google maps url showing only the buildings
      safeURL_Style = quote('feature:landscape.man_made|element:geometry.stroke|visibility:on|color:0xffffff|weight:1')
      urlBuildings = "http://maps.googleapis.com/maps/api/staticmap?center=" + str_Center + "&zoom=" + mapZoom + "&format=png32&sensor=false&size=" + str_Size + "&maptype=roadmap&style=visibility:off&style=" + safeURL_Style
      
      mainBuilding = None
      imgBuildings = io.imread(urlBuildings)
      gray_imgBuildings = color.rgb2gray(imgBuildings)
      # will create inverted binary image
      binary_imageBuildings = np.where(gray_imgBuildings > np.mean(gray_imgBuildings), 0.0, 1.0)
      contoursBuildings = find_contours(binary_imageBuildings, 0.1)
      
      for n, contourBuilding in enumerate(contoursBuildings):
          if (contourBuilding[0, 1] == contourBuilding[-1, 1]) and (contourBuilding[0, 0] == contourBuilding[-1, 0]):
              # check if it is inside any other polygon, so this will remove any additional elements
              isInside = False
              skipPoly = False
              for othersPolygon in contoursBuildings:
                  isInside = points_in_poly(contourBuilding, othersPolygon)
                  if all(isInside):
                      skipPoly = True
                      break
      
              if skipPoly == False:
                  center_inside = points_in_poly(np.array([[midX, midY]]), contourBuilding)
                  if center_inside:
              # approximate will generalize the polygon
                      mainBuilding = approximate_polygon(contourBuilding, tolerance=2)
      
      print(mainBuilding)
      

      现在,您可以使用小 JavaScript 和 Google Maps API 将像素坐标转换为纬度和经度:

      function point2LatLng(point, map) {
              var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
              var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
              var scale = Math.pow(2, map.getZoom());
              var worldPoint = new google.maps.Point(point.x / scale + bottomLeft.x, point.y / scale + topRight.y);
              return map.getProjection().fromPointToLatLng(worldPoint);
      }
      
      var convertedPointsMain = [];
      
      for (var i = 0; i < pxlMainPolygons[p].length; i++) {
          var conv_point = {
              x: Math.round(pxlMainPolygons[p][i][1]),
              y: Math.round(pxlMainPolygons[p][i][0])
          }; 
          convertedPointsMain[i] = point2LatLng(conv_point, map);
      }
      
      console.log(convertedPointsMain);
      

      【讨论】:

        【解决方案3】:

        我已经为此工作了几个小时,最接近的是找到一个请求 uri,它返回一个包含多边形的结果。我相信它通过editids 参数指定了建筑物(边界)。我们只需要一种从建筑物(边界)中获取当前编辑 ID 的方法。

        我的 URI 是:

        https://www.google.com/mapmaker?hl=en&gw=40&output=jsonp&ll=38.934911%2C-92.329359&spn=0.016288%2C0.056477&z=14&mpnum=0&vpid=1354239392511&editids=nAlkfrzSpBMuVg-hSJ&xauth=YOUR_XAUTH_HERE&geowiki_client=mapmaker&hl=en
        

        部分结果有需要的:

        "polygon":[{"gnew":{"loop":[{"vertex":[{"lat_e7":389364691,"lng_e7":-923341133},{"lat_e7":389362067,"lng_e7":-923342783},{"lat_e7":389361075,"lng_e7":-923343356},{"lat_e7":389360594,"lng_e7":-923342477},
        

        【讨论】:

        • 雷蒙德,谢谢分享!我仍在寻找解决方案。如何生成这样的 uri 以及如何从响应中提取多边形数据?有可能吗?
        【解决方案4】:

        我可以谦虚地建议您使用 OpenStreetMaps 来代替它吗?
        这要容易得多,因为这样您就可以使用OverPass API
        但是,多边形可能与谷歌地图或州调查不匹配。
        如果您使用 google-maps,后者也适用。

        // https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL
        private static string GetOqlBuildingQuery(int distance, decimal latitude, decimal longitude)
        {
            System.Globalization.NumberFormatInfo nfi = new System.Globalization.NumberFormatInfo()
            {
                NumberGroupSeparator = "",
                NumberDecimalSeparator = ".",
                CurrencyGroupSeparator = "",
                CurrencyDecimalSeparator = ".",
                CurrencySymbol = ""
            };
        
            // [out: json];
            // way(around:25, 47.360867, 8.534703)["building"];
            // out ids geom meta;
        
            string oqlQuery = @"[out:json];
        way(around:" + distance.ToString(nfi) + ", "
        + latitude.ToString(nfi) + ", " + longitude.ToString(nfi)
        + @")[""building""];
        out ids geom;"; // ohne meta - ist minimal
        
            return oqlQuery;
        }
        
        
        
        
        public static System.Collections.Generic.List<Wgs84Point> GetWgs84PolygonPoints(int distance, decimal latitude, decimal longitude)
        {
            string[] overpass_services = new string[] {
                "http://overpass.osm.ch/api/interpreter",
                "http://overpass.openstreetmap.fr/api/interpreter",
                "http://overpass-api.de/api/interpreter",
                "http://overpass.osm.rambler.ru/cgi/interpreter",
                // "https://overpass.osm.vi-di.fr/api/interpreter", // offline...
            };
        
            // string url = "http://overpass.osm.ch/api/interpreter";
            // string url = "http://overpass-api.de/api/interpreter";
            string url = overpass_services[s_rnd.Next(0, overpass_services.Length)];
        
        
            System.Collections.Specialized.NameValueCollection reqparm = new System.Collections.Specialized.NameValueCollection();
            reqparm.Add("data", GetOqlBuildingQuery(distance, latitude, longitude));
        
            string resp = PostRequest(url, reqparm);
            // System.IO.File.WriteAllText(@"D:\username\Documents\visual studio 2017\Projects\TestPlotly\TestSpatial\testResponse.json", resp, System.Text.Encoding.UTF8);
            // System.Console.WriteLine(resp);
            // string resp = System.IO.File.ReadAllText(@"D:\username\Documents\visual studio 2017\Projects\TestPlotly\TestSpatial\testResponse.json", System.Text.Encoding.UTF8);
        
            System.Collections.Generic.List<Wgs84Point> ls = null;
        
            Overpass.Building.BuildingInfo ro = Overpass.Building.BuildingInfo.FromJson(resp);
        
            if (ro != null && ro.Elements != null && ro.Elements.Count > 0 && ro.Elements[0].Geometry != null)
            {
                ls = new System.Collections.Generic.List<Wgs84Point>();
        
                for (int i = 0; i < ro.Elements[0].Geometry.Count; ++i)
                {
                    ls.Add(new Wgs84Point(ro.Elements[0].Geometry[i].Latitude, ro.Elements[0].Geometry[i].Longitude, i));
                } // Next i 
        
            } // End if (ro != null && ro.Elements != null && ro.Elements.Count > 0 && ro.Elements[0].Geometry != null) 
        
        
            return ls;
        } // End Function GetWgs84Points 
        

        【讨论】:

          【解决方案5】:

          我对这个问题很感兴趣,并写了一个解决方案。见my github project

          【讨论】:

            【解决方案6】:

            Google Maps API 包含一个GeocoderResults object,这可能是您需要的。特别是geometry 字段中返回的数据。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-03
              • 1970-01-01
              • 1970-01-01
              • 2012-08-31
              相关资源
              最近更新 更多