Akademisyenler öncülüğünde matematik/fizik/bilgisayar bilimleri soru cevap platformu
1 beğenilme 0 beğenilmeme
2.6k kez görüntülendi
Python'da enlem ve boylamları verilmiş iki nokta arasındaki yol nasıl bulunur ve harita üzerinde nasıl görselleştirilir?
Veri Bilimi kategorisinde (1.8k puan) tarafından  | 2.6k kez görüntülendi

1 cevap

0 beğenilme 0 beğenilmeme

Coğrafi konum verisi ile çalışmanın temelleri için öncelikle bu soruya bakabilirsiniz. Here Maps'in çevrimiçi servislerini kullanarak ilerleyeceğiz. Bunun için öncelikle linki takip ederek ücretsiz APP_ID ve API_KEY almanız gerekiyor. Bu uygulamada geopy ve görselleştirme için plotly ile mapbox kütüphanelerini de kullanacağız. Mapbox için de bir kullanıcı tokenı almanız gerekiyor, linki takip ederek bunu ücretsiz alabilirsiniz.

Gerekli kütüphaneleri yükleyelim ve yukarıdaki linkleri takip ederek aldığımız kodları eklyelim.

import pandas as pd
import requests
import json

from geopy.distance import geodesic

import plotly.graph_objs as go

import plotly.io as pio
pio.renderers.default = "browser"

here_app_id = '###'
here_api_key= '###'
mapbox_token = "###"

mapbox_access_token = mapbox_token

İki nokta arasındaki rota problemi oldukça karmaşık bir iş. En kısa yolu bulmak da bir mesele ama işin içerisine trafik, uzak durulması gereken bölgeler, araç çeşidi gibi parametreler de girdiğinde iyice zorlaşıyor. Ben bir yaya için iki nokta arasındaki en kısa yolu bulan bir örnek vereceğim. Here Maps'in rota bulma apisini kullanarak bunu yapacağız. Bu api https://route.ls.hereapi.com/routing/7.2/calculateroute.json adresinden ulaşılan bir rest servisi olarak çalışıyor, detaylı bilgi için bu linke bakabilirsiniz. routingpy ve herepy adlı kütüphaneler bu servisi python üzerinden rahatça kullanmamıza olanak tanıdıklarını söylüyorlar fakat güncel API_KEY ile çalışmıyorlar. Biz kendimiz python üzerinden aşağıdaki rest çağrısı ile bunu çözeceğiz.

payload = {'apiKey': here_api_key, 'waypoint0':'geo!40.984216,29.021948', 
           'waypoint1':'geo!40.98861,29.03451',
           'mode': 'fastest;pedestrian;traffic:disabled'}
r = requests.get('https://route.ls.hereapi.com/routing/7.2/calculateroute.json', params=payload)       

Yukarıdaki kodda payload atacağımız get isteğinin parametrelerini tanımlıyor. Bunun içerisindeki waypoint değerleri geo! işaretinden sonra enlem ve boylam bilgilerini içeriyor. Bu istekten dönen cevap uzunca ve içerisinde bir çok bilgi olan bir metin. Bu metni aşağıdaki kodla json formatına çevirelim.

a = json.loads(r.text) 

Bunun içerisinden iki nokta arasındaki rotayı tanımlayan enlem boylam bilgilerine aşağıdaki gibi ulaşabilirsiniz.

l = [i['position'] for i in a['response']['route'][0]['leg'][0]['maneuver']]
df = pd.DataFrame.from_dict(l)
df.head()

 	latitude 	longitude
0 	40.984250 	29.021920
1 	40.983907 	29.024076
2 	40.987040 	29.025675
3 	40.988628 	29.026726
4 	40.988402 	29.028701

Bu verisetinde ardışık koordinatlar arasında dümdüz gidiyoruz, kıscası rotamız bu.

Şimdi bu rota üzerinde hareket eden birisini görselleştirelim. Bunun için rota boyunca eşit uzunluklarda noktalar oluşturmamız lazım, bunu geopy kütüphanesinden geodesic fonksiyonunu kullanacağız. 

# i ve i+1 numaralı satırlar arasındaki mesafe 
dist_ar = [geodesic(df.loc[i], df.loc[i+1]).m for i in range(len(df)-1)]

# mesafeleri 10 metrelik kaç adımda gidebileceğimizi hesaplayalım
num_steps = [ max(round(dist/10),1) for dist in dist_ar]

# 10 metrelik adımlarla elde ettiğimiz enlem boylam bilgileri
new_lats = [ df['latitude'].iloc[j] * (1-(i / num_steps[j])) 
                                  + df['latitude'].iloc[j+1] * (i) / num_steps[j] 
            for j in range(len(df)-1)                      
            for i in range(num_steps[j]) ]

new_lons = [ df['longitude'].iloc[j] * (1-(i / num_steps[j])) 
                                  + df['longitude'].iloc[j+1] * (i) / num_steps[j] 
            for j in range(len(df)-1)                      
            for i in range(num_steps[j]) ]

# Varış noktasını da ekleyelim
new_lats.append(df['latitude'].iloc[-1])
new_lons.append(df['longitude'].iloc[-1])

Artık plotly ile bu rota üzerinde yürüyüşün animasyonunu yapabiliriz.

lats = new_lats
lons = new_lons

data = [go.Scattermapbox(
            lat= [29.021948],
            lon= [40.984216],
            #customdata = df['ADDRESS'],
            mode='markers',
            marker=dict(
                size= 6,
                color = 'gold',
                opacity = .8,
            ),
          )]


layout = go.Layout(autosize=False,
                   mapbox= dict(accesstoken=mapbox_token,
                                bearing=10,
                                pitch=10,
                                zoom=14,
                                center= dict(lat=40.9884,lon=29.027),
                                style = 'dark'
                                #style=shaz13_custom_style
                                ),
                    width=900,
                    height=600, 
                    title = "Yuruyus")
frames = [dict(data= [dict(type='scattermapbox',
                           lat= lats[k:k+1],
                           lon= lons[k:k+1] )],
               traces= [0],
               name='frame{}'.format(k)       
              )for k  in  range(1, len(new_lats))]           

layout.update(updatemenus=[dict(type='buttons', showactive=False,
                                y=0,
                                x=1.05,
                                xanchor='right',
                                yanchor='top',
                                pad=dict(t=0, r=10),
                                buttons=[dict(label='Play',
                                              method='animate',
                                              args=[None, 
                                                    dict(frame=dict(duration=100, 
                                                                    redraw=True),
                                                         transition=dict(duration=0),
                                                         fromcurrent=True,
                                                         mode='immediate'
                                                        )
                                                   ]
                                             )
                                        ]
                               )
                          ],
              );
fig=go.Figure(data=data,layout=layout, frames=frames)
fig.show()

Sonuç:

 

(1.8k puan) tarafından 
tarafından düzenlendi
Resimde tek nokta var sanki?
Hareketli gifti ama olmadi.
phyton'un ilgilenmediği alan yok sanırım.Bi ara görüntü işleme öğrenelim.
20,200 soru
21,728 cevap
73,275 yorum
1,887,879 kullanıcı