Abstract: Principle introduction Gaode Map provides an API interface for path planning. By outputting parameters such as starting and endin...
Principle introduction
Gaode Map provides an API interface for path planning. By outputting parameters such as starting and ending points, it can output the travel paths of different travel modes such as walking, public transportation, and driving. When there are enough starting and ending points, the road network can be generated by merging the planned travel paths. Therefore, the question includes several parts:
- How to generate enough starting and ending points automatically
- Based on how to get the travel path from the starting and ending points, and combine the travel paths from different starting and ending points
- Generate regional road network
Automatic generation of navigation start and end points
The search POI API interface provided by Gaud Map is used to extract the feature points within the specified area, and the feature points are regarded as the starting and ending coordinates of navigation. The specific implementation code is as follows:
import requests
import re
import json
import pandas as pd
def obtain_areapoilnglat(polygonlnglat,key,keywordslist=['School ',' Bank | ATM ',' Residential ',' McDonald's', 'KFC', 'Gas Station', 'Parking Lot', 'Hospital', 'Shopping Mall', 'Supermarket', 'Company', 'Hotel', 'Bus Station | Metro Station']:
#The key is the "Web Service API" key of Godmap, and you need to apply for it yourself
df_areapoi=pd.DataFrame()
for keywords in keywordslist:
#print(keywords)
pagenumber=1
length=20
while length>=20:
#print(pagenumber)
df_temp=poi(key,polygonlnglat,keywords,pagenumber)
pagenumber=pagenumber+1
length=len(df_temp)
df_areapoi=df_areapoi.append(df_temp,ignore_index=True)
return df_areapoi
def obtain_pdfromdicts(dicts):
df_areapoi=pd.DataFrame()
namelist=[address['name'] for address in dicts['pois']]
lnglist=[float(address['location'].split(",")[0]) for address in dicts['pois']]
latlist=[float(address['location'].split(",")[1]) for address in dicts['pois']]
df_areapoi['name']=namelist
df_areapoi['lng']=lnglist
df_areapoi['lat']=latlist
return df_areapoi
def poi(key:str,polygonlnglat:str,keywords:str,pagenumber:int)-> dict:
parameters = {
'key':key,
'polygon':polygonlnglat,
#'city':city,
'keywords':keywords,
'offset':20,
'page':pagenumber,
'output':'json'
}
r = requests.get('https://restapi.amap.com/v3/place/polygon?parameters',params = parameters)
data = r.json()
df_temp=obtain_pdfromdicts(data)
#print(df_temp)
return df_temp
Travel route extraction
The driving path planning results in json format can be obtained by inputting the parameters such as departure place, destination, route location, driving strategy and so on through the driving path planning API interface of Gaode Map:
The path planning result polyline is saved in the data frame format according to the mode of the minimum link unit (the minimum link has only two nodes: the starting point and the ending point). The sample data of the data frame result is as follows:
At the same time, the travel routes obtained from different starting and ending points are combined. When the designated area is large, the number of POI feature points extracted within the designated area will increase exponentially, and the number of navigation start and end points formed by pairwise combination of POI points will also increase exponentially. Considering the limitation of API interface calls and other factors, on the one hand, it is necessary to cluster POI points in blocks to reduce the number of navigation start and end points formed by pairwise combination of POI points. On the other hand, a maximum of 16 path points can be input in one call of the driving path planning API interface, which can make full use of this input parameter. In order to give readers space to think for themselves, this paper only gives how to use the path point parameter model to obtain road network data. Specifically, how to cluster POI points in blocks can be realized by the readers themselves.
The specific implementation code is as follows:
import numpy as np
def obtain_navigate(origin,destination,key,waypoints=[],key,strategy=0):
#The navigation path is generated based on the five parameters of starting point, destination, Gaud map API key, route point and navigation strategy
url="https://restapi.amap.com/v3/direction/driving?"
url=url+"origin="+str(origin[0])+","+str(origin[1])
url=url+"&destination="+str(destination[0])+","+str(destination[1])
url=url+"&extensions=base"
url=url+"&strategy="+str(strategy)+'&output=JSON'
if len(waypoints)>1:
url=url+"&waypoints="+str(waypoints[0][0])+","+str(waypoints[0][1])
for waypoint in waypoints[1:]:
url=url+";"+str(waypoint[0])+","+str(waypoint[1])
url=url+"&output=xml&key="+key
#print(url)
data= requests.get(url)
dicts=json.loads(data.text)
# pattern= re.compile(r'<step>(.*)</assistant_action>',re.M)
# steps=pattern.findall(data.text)
polyline_result=[]
t_sum=0
d_sum=0
waypoints_travel_list=[]
twowaypoints_navigate_result=[]
try:
for polyline in dicts['route']['paths'][0]['steps']:
navigate_result_polyline=[list(map(float,point.split(","))) for point in polyline['polyline'].split(";")]
#polyline_result=polyline_result+[list(map(float,point.split(","))) for point in polyline['polyline'].split(";")][1:-1] ###The first and last navigation paths between two points are removed
#print(polyline_result)
d_sum=d_sum+float(polyline['distance'])
t_sum=t_sum+float(polyline['duration'])
assistant_action=polyline['assistant_action']
twowaypoints_navigate_result=twowaypoints_navigate_result+navigate_result_polyline
if assistant_action=="Arrive at the destination" or assistant_action=="terminus ad quem":
twowaypoints_navigate_result=twowaypoints_navigate_result[1:-1]
polyline_result=polyline_result+twowaypoints_navigate_result
speed_average=d_sum/t_sum
waypoints_travel_list.append([d_sum,t_sum,speed_average])
t_sum=0
d_sum=0
twowaypoints_navigate_result=[]
t=[polyline_result[i] for i in range(1,len(polyline_result)) if polyline_result[i]!=polyline_result[i-1]]
polyline_result=[polyline_result[0]]+t
new=pd.DataFrame(polyline_result,columns=['lng','lat'])
new1=new.copy()
new1=new1.drop(new1.index[0])
new1.index=range(len(new1))
new1.columns=['nextlng','nextlat']
new2=new.copy()
new2=new2.drop(new2.index[-1])
new2.index=range(len(new2))
df_polyline_result=pd.concat([new1,new2],axis=1)
return df_polyline_result
except:
return pd.DataFrame()
def obtain_all_polyline_result(df_areapoi,waypointsmaxnumber=18):
#Combine the obtained poi point information to generate road network data
df_polyline_result_all=pd.DataFrame()
n=int(np.floor(len(df_areapoi)/waypointsmaxnumber))
for interval in range(1,n):
for i in range(0,int(np.floor(n/interval))):
for j in range(0,interval):
print(count)
count=count+1
startid=i*waypointsmaxnumber*interval+j
endid=(i+1)*waypointsmaxnumber*interval+j
kk=list(range(startid,endid,interval))
startid=kk[0]
endid=kk[-1]
origin=[df_areapoi.iloc[startid]['lng'],df_areapoi.iloc[startid]['lat']]
destination=[df_areapoi.iloc[endid]['lng'],df_areapoi.iloc[endid]['lat']]
waypoints= [[df_areapoi.loc[xx,'lng'],df_areapoi.loc[xx,'lat']] for xx in df_areapoi.iloc[kk].index]
df_polyline_result=obtain_navigate(origin,destination,waypoints)
df_polyline_result_all=df_polyline_result_all.append(df_polyline_result,ignore_index=True)
df_polyline_result_all=df_polyline_result_all.drop_duplicates()
return df_polyline_result_all
Regional road network generation
This part is mainly about writing the result data generated in the third step to generate the road network data in geojson format.
import time
import requests
import re
import json
outputfilename='xxx.geojson'
key="xxxxxx"
polygonlnglat='120.22084,30.2634|120.292021,30.130141'
df_areapoi=obtain_areapoilnglat(polygonlnglat,key)
df_polyline_result_all=obtain_all_polyline_result(df_areapoi,waypointsmaxnumber=18)
ODlnglat_navigate_obtainnetwork(df_polyline_result_all,outputfilename)
fp.close()
def pd_propertyresult_2geojson(pd_propertyresult,geotype,outputfilename):
#According to the obtained road network result data dataframe format, generate the road network in geojson format
#geotype='Point' MultiLineString LineString Three forms
fp = open(outputfilename,"w+")
#Write at the beginning of the file
st="""{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": ["""
fp.write(st+"\n")
stable_str1="""{"type": "Feature", "properties": {"""
stable_str2= """}, "geometry": { "type":\""""+geotype+"""\", "coordinates": """
#del str
for i in range(0,len(pd_propertyresult.index)):
#print(i)
geo_property=""" "id" """ +":"+"""\""""+str(i)+"""\""""+", "
geo_property=geo_property[:-1]
lnglat=[[pd_propertyresult.iloc[i]['lng'],pd_propertyresult.iloc[i]['lat']],[pd_propertyresult.iloc[i]['nextlng'],pd_propertyresult.iloc[i]['nextlat']]]
if i==len(pd_propertyresult.index)-1:
str1=stable_str1+geo_property+stable_str2+str(lnglat)+" } }"+"\n"
else:
str1=stable_str1+geo_property+stable_str2+str(lnglat)+" } },"+"\n"
fp.write(str1)
#print("str1:",str1)
#Write at the end of the file
st2="""]
}"""
fp.write(st2+"\n")
fp.close()
The resulting road network is as follows: