コード例 #1
0
        } // End Sub

        public static void GetAndInsertBuildingPolygon()
        {
            string sql = @"
INSERT INTO T_ZO_Objekt_Wgs84Polygon
(
	 ZO_OBJ_WGS84_UID
	,ZO_OBJ_WGS84_GB_UID
	,ZO_OBJ_WGS84_SO_UID
	,ZO_OBJ_WGS84_Sort
	,ZO_OBJ_WGS84_GM_Lat
	,ZO_OBJ_WGS84_GM_Lng
)
SELECT 
	 NEWID() ZO_OBJ_WGS84_UID -- uniqueidentifier
	,@gb_uid AS ZO_OBJ_WGS84_GB_UID -- uniqueidentifier
	,NULL AS ZO_OBJ_WGS84_SO_UID -- uniqueidentifier
	,@i ZO_OBJ_WGS84_Sort -- int
	,@lat ZO_OBJ_WGS84_GM_Lat -- decimal(23,20)
	,@lng ZO_OBJ_WGS84_GM_Lng -- decimal(23,20)
; 
";

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();


            ConnectionFactory fac = new ConnectionFactory(GetConnectionString());


            using (System.Data.Common.DbConnection connection = fac.Connection)
            {
                bool isZH = connection.ExecuteScalar <bool>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE (1=1) AND TABLE_TYPE= 'BASE TABLE' AND TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'T_GebaeudeIMMO' ");
                bool isRe = connection.ExecuteScalar <bool>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE (1=1) AND TABLE_TYPE= 'BASE TABLE' AND TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'T_Premises' ");

                string queryFile = "GetGbOsmPolygon.sql";
                if (isZH)
                {
                    queryFile = "GetGbOsmPolygon_STZH.sql";
                }
                else if (isRe)
                {
                    queryFile = "GetGbOsmPolygon_RE.sql";
                    throw new System.NotImplementedException("Query for RE not implemented.");
                }



                System.Collections.Generic.List <BuildingToGeoCode> ls = System.Linq.Enumerable.ToList(
                    connection.Query <BuildingToGeoCode>(queryFile, typeof(OsmPolyonFinder))
                    );

                foreach (BuildingToGeoCode building in ls)
                {
                    System.Threading.Thread.Sleep(4000);

                    GeoApis.Polygon nearestBuilding = GetNearestBuildingPolygon(building.GB_GM_Lat, building.GB_GM_Lng);
                    if (nearestBuilding == null)
                    {
                        continue;
                    }

                    System.Console.WriteLine(nearestBuilding);
                    System.Console.WriteLine(nearestBuilding.OsmId); // 218003784

                    GeoApis.LatLng[] msPoints      = nearestBuilding.ToClockWiseLatLngPoints();
                    string           createPolygon = CreateSqlPolygon(msPoints);
                    System.Console.WriteLine(sql);

                    //SELECT
                    //	 geography::STPolyFromText('POLYGON((7.7867531 46.9361500,7.7869622 46.9361188,7.7869515 46.9360856,7.7869952 46.9360793,7.7870059 46.9361123,7.7870300 46.9361087,7.7870312 46.9361124,7.7870944 46.9361028,7.7870933 46.9360991,7.7872340 46.9360778,7.7873147 46.9363299,7.7871740 46.9363510,7.7871728 46.9363473,7.7871099 46.9363568,7.7871110 46.9363605,7.7868341 46.9364021,7.7867531 46.9361500))', 4326)
                    //	,geometry::STPolyFromText('POLYGON((7.7867531 46.9361500,7.7869622 46.9361188,7.7869515 46.9360856,7.7869952 46.9360793,7.7870059 46.9361123,7.7870300 46.9361087,7.7870312 46.9361124,7.7870944 46.9361028,7.7870933 46.9360991,7.7872340 46.9360778,7.7873147 46.9363299,7.7871740 46.9363510,7.7871728 46.9363473,7.7871099 46.9363568,7.7871110 46.9363605,7.7868341 46.9364021,7.7867531 46.9361500))', 4326)

                    //	-- Geometry is BAD for area
                    //	,geography::STPolyFromText('POLYGON((7.7867531 46.9361500,7.7869622 46.9361188,7.7869515 46.9360856,7.7869952 46.9360793,7.7870059 46.9361123,7.7870300 46.9361087,7.7870312 46.9361124,7.7870944 46.9361028,7.7870933 46.9360991,7.7872340 46.9360778,7.7873147 46.9363299,7.7871740 46.9363510,7.7871728 46.9363473,7.7871099 46.9363568,7.7871110 46.9363605,7.7868341 46.9364021,7.7867531 46.9361500))', 4326).STArea() AS geogArea
                    //	,geometry::STPolyFromText('POLYGON((7.7867531 46.9361500,7.7869622 46.9361188,7.7869515 46.9360856,7.7869952 46.9360793,7.7870059 46.9361123,7.7870300 46.9361087,7.7870312 46.9361124,7.7870944 46.9361028,7.7870933 46.9360991,7.7872340 46.9360778,7.7873147 46.9363299,7.7871740 46.9363510,7.7871728 46.9363473,7.7871099 46.9363568,7.7871110 46.9363605,7.7868341 46.9364021,7.7867531 46.9361500))', 4326).STArea() AS geomArea
                    //";



                    GeoApis.LatLng[] osmPoints = nearestBuilding.ToCounterClockWiseLatLngPoints();

                    string sql2 = "DELETE FROM T_ZO_Objekt_Wgs84Polygon WHERE ZO_OBJ_WGS84_GB_UID = @gb_uid; ";
                    connection.Execute(sql2, new { gb_uid = building.GB_UID });


                    for (int i = 0; i < osmPoints.Length; ++i)
                    {
                        connection.Execute(sql,
                                           new
                        {
                            gb_uid = building.GB_UID,
                            i      = i,
                            lat    = osmPoints[i].lat,
                            lng    = osmPoints[i].lng
                        }
                                           );
                    } // Next i
                }     // Next building
            }         // End Using connection
        }             // End Sub GetAndInsertBuildingPolygon
コード例 #2
0
        public static GeoApis.Polygon GetNearestBuildingPolygon(decimal latitide, decimal longitude)
        {
            OpenToolkit.Mathematics.DecimalVector2 geoPoint = new OpenToolkit.Mathematics.DecimalVector2(latitide, longitude);

            GeoApis.LatLngBounds bounds = GeoApis.LatLngBounds.FromPoint(
                new GeoApis.LatLng(latitide, longitude)
                , 1000
                ); // this is, radius = 500m

            decimal area = bounds.BoundsArea;

            if (area > 0.25m)
            {
                System.Console.WriteLine("The maximum bbox size is 0.25, and your request was too large.\nEither request a smaller area, or use planet.osm.");
                return(null);
            } // End if (area > 0.25m)


            string xml = null;

#if fromFile
            xml = System.IO.File.ReadAllText(@"D:\Stefan.Steiger\Desktop\map.osm.xml", System.Text.Encoding.UTF8);
#else
            const string OSM_API_VERSION = "0.6";
            // string url = "https://www.openstreetmap.org/api/0.6/map?bbox=8.626273870468141,47.69679769756054,8.636573553085329,47.700530864557194&no_cache=1562588642802";
            string url = "https://www.openstreetmap.org/api/" + OSM_API_VERSION + "/map?bbox=" + bounds.ToBBoxString();



            string[] proxyList = ProxyHelper.GetProxyArray();
            string   proxy     = null;

REPEAT_UNTIL_SUCCESS:
            proxy = proxyList[s_rnd.Next(0, proxyList.Length)];

            // proxy = "139.162.38.191:80";
            // proxy = "178.128.51.105";
            // proxy = "105.27.237.27:80";

            proxy = "161.117.251.194:80";
            proxy = "42.3.51.114:80";
            proxy = "173.212.202.65:80";
            proxy = "47.91.105.34:80";

            try
            {
                using (System.Net.WebClient wc = new WebClientWithCustomTimeout(15))
                {
                    // wc.Proxy = new System.Net.WebProxy(proxy);

                    xml = wc.DownloadString(url);
                } // End Using wc
            }
            catch (System.Net.WebException webEx)
            {
                System.Console.WriteLine(webEx.Message);
                System.Console.WriteLine(webEx.Status);

                if (webEx.Status == System.Net.WebExceptionStatus.Timeout)
                {
                    System.Console.WriteLine("Timeout ! ");
                }
                else if (webEx.Status == System.Net.WebExceptionStatus.ProtocolError)
                {
                    System.Console.WriteLine("ProtocolError");
                }

                System.Net.HttpWebResponse response = webEx.Response as System.Net.HttpWebResponse;
                if (response != null)
                {
                    System.Console.WriteLine("HTTP Status Code: " + response.StatusCode.ToString() + ", " + response.StatusDescription);

                    if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        System.Console.WriteLine("401");
                    }

                    string responseHtml = null;
                    using (System.IO.Stream responseStream = response.GetResponseStream())
                    {
                        using (System.IO.TextReader tr = new System.IO.StreamReader(responseStream))
                        {
                            responseHtml = tr.ReadToEnd();
                        }
                    }

                    System.Console.WriteLine(responseHtml);
                }
                else
                {
                    // no http status code available
                }

                // goto REPEAT_UNTIL_SUCCESS;
            }
            catch (System.Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                // goto REPEAT_UNTIL_SUCCESS;
            }
#endif


            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml(xml);

            System.Xml.XmlNodeList nodes = doc.SelectNodes("//node");


            System.Collections.Generic.Dictionary <string, GeoApis.LatLng> nodeDictionary =
                new System.Collections.Generic.Dictionary <string, GeoApis.LatLng>(
                    System.StringComparer.InvariantCultureIgnoreCase
                    );

            System.Collections.Generic.Dictionary <string, GeoApis.Polygon> buildingPolygonDictionary =
                new System.Collections.Generic.Dictionary <string, GeoApis.Polygon>(
                    System.StringComparer.InvariantCultureIgnoreCase
                    );



            if (nodes.Count > 1000)
            {
                System.Console.WriteLine(nodes.Count);
                throw new System.InvalidOperationException("Densely populated area. Too many nodes to process");
                return(null);
            }


            foreach (System.Xml.XmlElement node in nodes)
            {
                string id       = node.GetAttribute("id");
                string nodeLat  = node.GetAttribute("lat");
                string nodeLong = node.GetAttribute("lon");

                decimal dlat  = 0;
                decimal dlong = 0;
                decimal.TryParse(nodeLat, out dlat);
                decimal.TryParse(nodeLong, out dlong);

                nodeDictionary[id] = new GeoApis.LatLng(dlat, dlong);
            } // Next node


            // https://stackoverflow.com/questions/1457638/xpath-get-nodes-where-child-node-contains-an-attribute
            // querySelectorAll('way tag[k="building"]')
            System.Xml.XmlNodeList buildings = doc.SelectNodes("//way[tag/@k=\"building\"]");
            foreach (System.Xml.XmlElement building in buildings)
            {
                System.Collections.Generic.List <GeoApis.LatLng> lsPolygonPoints =
                    new System.Collections.Generic.List <GeoApis.LatLng>();

                System.Xml.XmlNodeList buildingNodes = building.SelectNodes("./nd");
                foreach (System.Xml.XmlElement buildingNode in buildingNodes)
                {
                    string reff = buildingNode.GetAttribute("ref");
                    lsPolygonPoints.Add(nodeDictionary[reff]);
                } // Next buildingNode

                GeoApis.LatLng[] polygonPoints = toCounterClockWise(lsPolygonPoints.ToArray());
                string           id            = building.GetAttribute("id");

                GeoApis.Polygon poly = new GeoApis.Polygon(polygonPoints);
                poly.OsmId = id;

                buildingPolygonDictionary[id] = poly;
            } // Next building

            // System.Console.WriteLine(buildingPolygonDictionary);



            decimal?min = null;
            string  uid = null;

            foreach (System.Collections.Generic.KeyValuePair <string, GeoApis.Polygon> kvp in buildingPolygonDictionary)
            {
                if (OsmPolygonHelper.IsInside(kvp.Value.Points, geoPoint))
                {
                    uid = kvp.Key;
                    min = 0;
                    break;
                }

                decimal minDist = kvp.Value.GetMinimumDistance(geoPoint);

                if (min.HasValue)
                {
                    if (minDist < min.Value)
                    {
                        min = minDist;
                        uid = kvp.Key;
                    } // End if (minDist < min.Value)
                }
                else
                {
                    uid = kvp.Key;
                    min = minDist;
                }
            } // Next kvp

            if (uid == null || !buildingPolygonDictionary.ContainsKey(uid))
            {
                return(null);
            }

            return(buildingPolygonDictionary[uid]);
        } // End Sub