Построение улиц с помощью ggmap и geom_path - PullRequest
0 голосов
/ 29 апреля 2018

Мне нравится строить улицы с ggmap в определенной области. Я получил данные из OSM через API путепровода. Это работает довольно хорошо для большинства улиц с geom_path. Однако, некоторые улицы перепутаны. Любые советы приветствуются.

Пожалуйста, посмотрите на http://overpass -turbo.eu / для желаемого результата. Вы можете найти запрос в R-код ниже.

library(httr)
library(tidyverse)
#> ── Attaching packages ─────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
#> ✔ ggplot2 2.2.1     ✔ purrr   0.2.4
#> ✔ tibble  1.4.2     ✔ dplyr   0.7.4
#> ✔ tidyr   0.8.0     ✔ stringr 1.3.0
#> ✔ readr   1.1.1     ✔ forcats 0.3.0
#> ── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
#> ✖ dplyr::filter() masks stats::filter()
#> ✖ dplyr::lag()    masks stats::lag()
library(ggmap)
library(rlist)


# Get data from overpass api
query <- paste('[out:json];',
  '(way["highway"~"primary|residential"](53.5970, 9.9010, 53.6050, 9.9080););',
  '(._;>;);',
  'out body;')
url <- 'http://overpass-api.de/api/interpreter'
r <- POST(url = url, body = query, encode = 'json')


# Tidy data
nodes <- content(r)$elements %>% list.filter(type == 'node')
ways <- content(r)$elements %>% list.filter(type == 'way')

df_nodes <- nodes %>% 
  list.select(type, id, lat, lon) %>%
  bind_rows()

df_ways <- ways %>% 
  lapply(function(x) list.append(x, street = x$tags$name)) %>%
  list.select(street, nodes)
df_ways <- map(df_ways, function(x) x %>% as_tibble) %>% 
  bind_rows() %>% 
  mutate(id = unlist(nodes))

df <- df_ways %>% left_join(df_nodes, by = 'id')
head(df)
#> # A tibble: 6 x 6
#>   street           nodes            id type    lat   lon
#>   <chr>            <list>        <dbl> <chr> <dbl> <dbl>
#> 1 Reichsbahnstraße <int [1]>  38893884 node   53.6  9.91
#> 2 Reichsbahnstraße <int [1]>  55079985 node   53.6  9.91
#> 3 Reichsbahnstraße <int [1]>  38893882 node   53.6  9.91
#> 4 Reichsbahnstraße <int [1]>  38893881 node   53.6  9.91
#> 5 Reichsbahnstraße <int [1]> 380820539 node   53.6  9.91
#> 6 Reichsbahnstraße <int [1]>  38893879 node   53.6  9.91


# Get map
lat <- (max(df$lat)+min(df$lat))/2
lon <- (max(df$lon)+min(df$lon))/2
hamburg <- get_map(location = c(lon = lon, lat = lat), zoom = 16)
#> Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=53.601726,9.90531&zoom=16&size=640x640&scale=2&maptype=terrain&language=en-EN&sensor=false


# Plot
ggmap(hamburg) +
  geom_path(data = df, aes(x = lon, y = lat, color = street), size = 2)
#> Warning: Removed 3 rows containing missing values (geom_path).

'Actual Output' 'Desired Output'

1 Ответ

0 голосов
/ 03 мая 2018

Эта проблема возникает, когда на улице много ветвей, так как geom_path() будет просто связывать каждые две последовательные точки прямой линией.

Давайте возьмем «Рейхсбанштрассе» в качестве примера:

lon <- df %>% filter(street == "Reichsbahnstraße") %>% .$lon
lat <- df %>% filter(street == "Reichsbahnstraße") %>% .$lat
lat[1] == lat[41] & lon[1] == lon[41]
# returns TRUE

geom_path() начинается с точки 1 (точка пересечения, см. Ниже), рисует одну часть улицы (идет на северо-восток), а затем снова возвращается к точке пересечения (индекс 41), чтобы нарисовать следующую филиал.

Чтобы избежать этого, вы можете вернуться к точке пересечения по той же дороге, прежде чем рисовать другую ветку (например, вместо c(7, 8, 9, 10, 7, 6) do c(7, 8, 9, 10, 9, 8, 7, 6)). Вроде того, что вы бы сделали, если бы вы пытались нарисовать улицу карандашом, не снимая ее с листа бумаги.

enter image description here

...