get_beijing_roadnetwork(工作太忙,仅仅作为记录)

  1 from shapely.geometry import Polygon, LinearRing
  2 import xml.etree.cElementTree as et
  3 import matplotlib.pyplot as plt
  4 from networkx import DiGraph
  5 import geopandas as gpd
  6 import numpy as np
  7 from pyproj import CRS
  8 
  9 # default CRS to set when creating graphs
 10 default_crs = "epsg:4326"
 11 
 12 def is_projected(crs):
 13     """
 14     Determine if a coordinate reference system is projected or not.
 15 
 16     This is a convenience wrapper around the pyproj.CRS.is_projected function.
 17 
 18     Parameters
 19     ----------
 20     crs : string or pyproj.CRS
 21         the coordinate reference system
 22 
 23     Returns
 24     -------
 25     projected : bool
 26         True if crs is projected, otherwise False
 27     """
 28     return CRS.from_user_input(crs).is_projected
 29 
 30 def project_gdf(gdf, to_crs=None, to_latlong=False):
 31     """
 32     Project a GeoDataFrame from its current CRS to another.
 33 
 34     If to_crs is None, project to the UTM CRS for the UTM zone in which the
 35     GeoDataFrame's centroid lies. Otherwise project to the CRS defined by
 36     to_crs. The simple UTM zone calculation in this function works well for
 37     most latitudes, but may not work for some extreme northern locations like
 38     Svalbard or far northern Norway.
 39 
 40     Parameters
 41     ----------
 42     gdf : geopandas.GeoDataFrame
 43         the GeoDataFrame to be projected
 44     to_crs : string or pyproj.CRS
 45         if None, project to UTM zone in which gdf's centroid lies, otherwise
 46         project to this CRS
 47     to_latlong : bool
 48         if True, project to settings.default_crs and ignore to_crs
 49 
 50     Returns
 51     -------
 52     gdf_proj : geopandas.GeoDataFrame
 53         the projected GeoDataFrame
 54     """
 55     if gdf.crs is None or len(gdf) < 1:  # pragma: no cover
 56         raise ValueError("GeoDataFrame must have a valid CRS and cannot be empty")
 57 
 58     # if to_latlong is True, project the gdf to latlong
 59     if to_latlong:
 60         gdf_proj = gdf.to_crs(default_crs)
 61         print(f"Projected GeoDataFrame to {default_crs}")
 62 
 63     # else if to_crs was passed-in, project gdf to this CRS
 64     elif to_crs is not None:
 65         gdf_proj = gdf.to_crs(to_crs)
 66         print(f"Projected GeoDataFrame to {to_crs}")
 67 
 68     # otherwise, automatically project the gdf to UTM
 69     else:
 70         if is_projected(gdf.crs):  # pragma: no cover
 71             raise ValueError("Geometry must be unprojected to calculate UTM zone")
 72 
 73         # calculate longitude of centroid of union of all geometries in gdf
 74         avg_lng = gdf["geometry"].unary_union.centroid.x
 75 
 76         # calculate UTM zone from avg longitude to define CRS to project to
 77         utm_zone = int(np.floor((avg_lng + 180) / 6) + 1)
 78         utm_crs = f"+proj=utm +zone={utm_zone} +ellps=WGS84 +datum=WGS84 +units=m +no_defs"
 79 
 80         # project the GeoDataFrame to the UTM CRS
 81         gdf_proj = gdf.to_crs(utm_crs)
 82         print(f"Projected GeoDataFrame to {gdf_proj.crs}")
 83 
 84     return gdf_proj
 85 
 86 def project_geometry(geometry, crs=None, to_crs=None, to_latlong=False):
 87     """
 88     Project a shapely geometry from its current CRS to another.
 89 
 90     If to_crs is None, project to the UTM CRS for the UTM zone in which the
 91     geometry's centroid lies. Otherwise project to the CRS defined by to_crs.
 92 
 93     Parameters
 94     ----------
 95     geometry : shapely.geometry.Polygon or shapely.geometry.MultiPolygon
 96         the geometry to project
 97     crs : string or pyproj.CRS
 98         the starting CRS of the passed-in geometry. if None, it will be set to
 99         settings.default_crs
100     to_crs : string or pyproj.CRS
101         if None, project to UTM zone in which geometry's centroid lies,
102         otherwise project to this CRS
103     to_latlong : bool
104         if True, project to settings.default_crs and ignore to_crs
105 
106     Returns
107     -------
108     geometry_proj, crs : tuple
109         the projected geometry and its new CRS
110     """
111     if crs is None:
112         crs = default_crs
113 
114     gdf = gpd.GeoDataFrame(geometry=[geometry], crs=crs)
115     gdf_proj = project_gdf(gdf, to_crs=to_crs, to_latlong=to_latlong)
116     geometry_proj = gdf_proj["geometry"].iloc[0]
117     return geometry_proj, gdf_proj.crs
118 
119 def get_bj_ring_road(osmfile=r"./beijing_6ring_multiways.osm", buffer_distance=1000, show=True):
120     # # beijing_xring road.osm as the input data
121     root = et.parse(osmfile).getroot()
122 
123     nodes = {}
124     for node in root.findall('node'):
125         nodes[int(node.attrib['id'])] = (float(node.attrib['lon']), float(node.attrib['lat']))
126     edges = []
127     way_count = len(root.findall('way'))
128     if way_count > 1:# multiways in osm
129         for way in root.findall('way'):
130             element_nd = way.findall('nd')
131             node_s, node_e = int(element_nd[0].attrib['ref']), int(element_nd[1].attrib['ref'])
132             path = (node_s, node_e)
133             edges.append(path)
134     elif way_count == 1:# one way in osm
135         way_nodes = []
136         for element_nd in root.findall('way')[0].findall('nd'):
137             way_nd_index = element_nd.attrib['ref']
138             way_nodes.append(int(way_nd_index))
139         for i in range(len(way_nodes)-1):# a way must include two points
140             node_s, node_e = way_nodes[i], way_nodes[i+1]
141             path = (node_s, node_e)
142             edges.append(path)
143     else:# error osm
144         print("OSM Error!")
145         return None, None, None, None
146 
147     edge = edges[0]
148     E = []
149     E.append(edge)
150     edges.remove(edge)
151     point_s, point_e = nodes[E[0][0]], nodes[E[0][1]]
152     Point_lists = []
153     Point_lists.append(list(point_s))
154     Point_lists.append(list(point_e))
155     while len(edges) > 0:
156         (node_f_s, node_f_e) = E[-1]
157         for (node_n_s, node_n_e) in edges:
158             if node_f_e == node_n_s:
159                 E.append((node_n_s, node_n_e))
160                 point_f_e = nodes[node_n_e]
161                 Point_lists.append(list(point_f_e))
162                 # print((node_n_s, node_n_e))
163                 edges.remove((node_n_s, node_n_e))
164                 break
165     # Points.pop()
166     print(E[0], '...', E[-2], E[-1])
167     print(Point_lists[0], '...', Point_lists[-2], Point_lists[-1])
168     road_line_arr = np.array(Point_lists)  # 转换成二维坐标表示
169 
170     ring_plg = Polygon(road_line_arr)  # Polygon
171     ring_lr = LinearRing(road_line_arr)  # LinearRing
172 
173     ring_lr_proj, crs_utm = project_geometry(ring_lr)# 平面投影
174     ring_lr_proj_buff =ring_lr_proj.buffer(buffer_distance)# buffer
175     ring_lr_buf, ring_lr_buf_epsg = project_geometry(ring_lr_proj_buff, crs=crs_utm, to_latlong=True) # 反平面投影  LinearRing buffer
176 
177     poly_proj, crs_utm = project_geometry(ring_plg)# 平面投影
178     poly_proj_buff = poly_proj.buffer(buffer_distance)# buffer
179     ring_plg_buf, poly_buff_epsg = project_geometry(poly_proj_buff, crs=crs_utm, to_latlong=True)# 反平面投影  Polygon buffer
180 
181     if show:
182         # Draw the geo with geopandas
183         geo_lrg = gpd.GeoSeries(ring_lr)  # LinearRing
184         geo_lrg.plot()
185         plt.xlabel("$lon$")
186         plt.ylabel("$lat$")
187         plt.title("$LinearRing$")
188         plt.show()
189 
190         geo_lrg_buf = gpd.GeoSeries(ring_lr_buf)  # LinearRing buffer
191         geo_lrg_buf.plot()
192         plt.xlabel("$lon$")
193         plt.ylabel("$lat$")
194         plt.title("$LinearRing-with-buffer$")
195         plt.show()
196 
197         geo_plg = gpd.GeoSeries(ring_plg)  # Polygon
198         geo_plg.plot()
199         plt.xlabel("$lon$")
200         plt.ylabel("$lat$")
201         plt.title("$Polygon$")
202         plt.show()
203 
204         geo_plg = gpd.GeoSeries(ring_plg_buf)  # Polygon
205         geo_plg.plot()
206         plt.xlabel("$lon$")
207         plt.ylabel("$lat$")
208         plt.title("$Polygon-with-buffer$")
209         plt.show()
210 
211     return ring_lr, ring_lr_buf, ring_plg, ring_plg_buf
212 
213 # road_6ring_lr, road_6ring_lr_buf, road_6ring_plg, road_6ring_plg_buf = get_bj_ring_road(osmfile=r"./beijing_6ring_multiways.osm", buffer_distance=1000, show=True)
214 road_2ring_lr, road_2ring_lr_buf, road_2ring_plg, road_2ring_plg_buf = get_bj_ring_road(osmfile=r"./beijing_2ring.osm", buffer_distance=1000, show=True)
215 
216 # test
217 # # buffer_dist = 500
218 # # poly_proj, crs_utm = project_geometry(road_2ring_plg)
219 # # poly_proj_buff = poly_proj.buffer(buffer_dist)
220 # # poly_buff, poly_buff_epsg = project_geometry(poly_proj_buff, crs=crs_utm, to_latlong=True)
221 # # ring_lr_proj, crs_utm = project_geometry(road_2ring_lr)
222 # # ring_lr_proj_buff = ring_lr_proj.buffer(buffer_dist)
223 # # ring_lr_buff, ring_lr_buff_epsg = project_geometry(ring_lr_proj_buff, crs=crs_utm, to_latlong=True)
224 
225 import osmnx as ox
226 from osmnx import geocoder, graph_from_polygon, graph_from_xml
227 from osmnx import save_graph_shapefile, save_graph_xml, plot_graph
228 
229 ######## Create a graph from OSM and save the graph to .osm ########
230 # 下载数据
231 
232 # ox.settings
233 utn = ox.settings.useful_tags_node
234 oxna = ox.settings.osm_xml_node_attrs
235 oxnt = ox.settings.osm_xml_node_tags
236 utw = ox.settings.useful_tags_way
237 oxwa = ox.settings.osm_xml_way_attrs
238 oxwt = ox.settings.osm_xml_way_tags
239 utn = list(set(utn + oxna + oxnt))
240 utw = list(set(utw + oxwa + oxwt))
241 ox.config(all_oneway=True, useful_tags_node=utn, useful_tags_way=utw)
242 
243 # Create a graph from OSM within the boundaries of some shapely polygon.
244 M = graph_from_polygon(polygon=road_2ring_plg_buf,
245                        network_type='drive', # network_type : {"all_private", "all", "bike", "drive", "drive_service", "walk"}
246                        simplify=True,# if True, simplify graph topology with the `simplify_graph` function
247                        retain_all=False,# if True, return the entire graph even if it is not connected.
248                        truncate_by_edge=True,# if True, retain nodes outside boundary polygon if at least one of node's neighbors is within the polygon
249                        clean_periphery=True,# if True, buffer 500m to get a graph larger than requested, then simplify, then truncate it to requested spatial boundaries
250                        custom_filter=None)# a custom ways filter to be used instead of the network_type presets, e.g., '["power"~"line"]' or '["highway"~"motorway|trunk"]'.
251 # 可能因为代理问题, 则需要 Win+R -- (输入)regedit -- 删除 计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings下的 ProxyEnable、ProxyOverride、ProxyServer 后重新运行程序
252 print('number_of_nodes:', M.number_of_nodes(), 'number_of_edges:', M.number_of_edges())
253 plot_graph(M, figsize=(32, 32), node_size=15, dpi=600, save=True, filepath='./images/ring_graph.png')
254 # save_graph_xml(M, filepath='./download_osm/graph.osm')
255 save_graph_shapefile(M, 'download_shp')
256 
257 # Convert M to DiGraph G
258 G = DiGraph(M, directed=True)
259 
260 nodes = G.nodes()  # 获取图中的所有节点
261 nd_data = G.nodes.data(data=True)  # 获得所有节点的属性
262 print(list(nd_data)[-1])
263 # simplify (9094448576, {'y': 39.8708445, 'x': 116.3840209, 'street_count': 3})
264 # full (9094448578, {'y': 39.8707558, 'x': 116.3840692, 'highway': 'crossing', 'street_count': 2})
265 eg_data = G.edges(data=True)  # 获得所有边的属性
266 print(list(eg_data)[-1])
267 # simplify (9094448576, 9063939428, {'osmid': [955313155, 26295235, 955313156], 'oneway': 'yes', 'highway': 'tertiary', 'length': 393.366, 'tunnel': 'yes', 'geometry': <shapely.geometry.linestring.LineString object at 0x0000020FBD457630>})
268 # full (9094448578, 9094448574, {'osmid': 983612462, 'oneway': 'yes', 'highway': 'trunk_link', 'length': 3.189})
269 print('number_of_nodes:', G.number_of_nodes())
270 print('number_of_edges:', G.number_of_edges())

北京23456环路OSM数据见百度网盘:链接:https://pan.baidu.com/s/1Y3H0s9natD77rgDP-kMvxQ 

提取码:8866

上一篇:Shell:sed工具


下一篇:C++翻译A1042 Shuffling题解