r - 传单折线不超过日期变更线传单

标签 r leaflet polyline r-sp geosphere

对于一个 Shiny 的大学项目,我面临着跨越太平洋日期变更线的折线问题。从一个中心(武汉)我想创建 72 条线路,显示它们连接不同地区。我已经创建了一个循环,以确保经度 > 0 已更改为大于 0 的经度。有人有解决方案使折线正确穿过日期变更线吗?

在照片中你可以看到我当前的情节没有正确跨越界限。

library(leaflet)
library(geosphere)
library(sp)

df <- read.table(text = "
Longitude.Central Latitude.Central Longitude Latitude
112.2707         30.97564  117.2264 31.82571
112.2707         30.97564  116.4142 40.18238
112.2707         30.97564    4.4699 50.50390
112.2707         30.97564  -71.0589 42.36010
112.2707         30.97564 -123.1210 49.28270
112.2707         30.97564  104.9910 12.56570",
           header = TRUE)

p1 <- as.matrix(df[,c(1,2)])
p2 <- data.frame(df[,c(3,4)])

p3 <- matrix(nrow = length(p2))
for (j in 1:nrow(p2)) {
  if (p2[j,]$Longitude < 0) {
    p3[j] <- p2[j,]$Longitude + 360
  } else {
    p3[j] <- p2[j,]$Longitude
  }
}

p2 <- as.matrix(cbind(p3, p2$Latitude))
df2 <- gcIntermediate(
  p1, p2, 
  n = 72, 
  addStartEnd = TRUE,
  sp = T)

leaflet( ) %>% 
    setView(df$Longitude.Central[[1]], lat = df$Latitude.Central[[1]], 1) %>%
    addTiles(urlTemplate = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png") %>% 
    addPolylines(data = df2, weight = 1
    )

# Head of the data
> head(df)
# A tibble: 6 x 4
  Longitude.Central Latitude.Central Longitude Latitude
              <dbl>            <dbl>     <dbl>    <dbl>
1          112.2707         30.97564  117.2264 31.82571
2          112.2707         30.97564  116.4142 40.18238
3          112.2707         30.97564    4.4699 50.50390
4          112.2707         30.97564  -71.0589 42.36010
5          112.2707         30.97564 -123.1210 49.28270
6          112.2707         30.97564  104.9910 12.56570

Output Shiny

最佳答案

您可以尝试以下几种方法。一种是使用 gcIntermediate 中的 breakAtDateLine = TRUE 选项:

df2 <- gcIntermediate(
  p1, p2, 
  n = 72, 
  addStartEnd = TRUE,
  sp = T,
  breakAtDateLine = T)

leaflet( ) %>% 
  setView(lng = df$Longitude.Central[[1]], lat = df$Latitude.Central[[1]], 1) %>%
  addTiles(urlTemplate = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png") %>% 
  addPolylines(data = df2, weight = 1
  )

正如您所看到的,它打破了线条,但在屏幕左侧继续它,这并不理想。

enter image description here

我们可以尝试的另一件事是使用 breakAtDateLine = FALSE 运行 gcIntermediate 函数,并在运行该函数后手动调整纬度和经度。如果我们设置 sp=FALSE,这将是最简单的。

请注意,我们只需要修正从我们所在位置向东延伸的线 - 这些是唯一跨越日期变更线的线。每个位置的情况并不相同,但逻辑应该相似。

p1 <- as.matrix(df[,c(1,2)])
p2 <- data.frame(df[,c(3,4)])

df2 <- gcIntermediate(
  as.matrix(p1),
  as.matrix(p2), 
  n = 72, 
  addStartEnd = TRUE,
  breakAtDateLine = F,
  sp = F)

# correct the longitudes
res <- lapply(df2, function(x) {
  # if direction is east, correct lon, else don't
  if(x[,'lon'][2] - x[,'lon'][1]  > 0){
    cbind(lon =ifelse(x[,'lon']<0, x[,'lon'] + 360, x[,'lon']), lat = x[,'lat'])
  } else {
    x
  }
})

# and convert back to sp (I just took this code from the gcIntermediate function)
for (i in 1:length(res)) {
  if (!is.list(res[[i]])) {
    res[[i]] <- Lines(list(Line(res[[i]])), ID = as.character(i))
  }
  else {
    res[[i]] <- Lines(list(Line(res[[i]][[1]]), Line(res[[i]][[2]])), 
                      ID = as.character(i))
  }
}

res <- SpatialLines(res, CRS("+proj=longlat +ellps=WGS84"))


leaflet() %>% 
  setView(df$Latitude.Central[[1]], lat = df$Longitude.Central[[1]], 1) %>%
  addTiles(urlTemplate = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png") %>% 
  addPolylines(data = res, weight = 1) 

enter image description here

当它到达 map 顶部时,它仍然有点奇怪,但希望这是你可以忍受的事情

关于r - 传单折线不超过日期变更线传单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60382231/

相关文章:

r - 确定最佳簇数并使用 Daisy 函数和 Gower 相似度

r - 在有向图中设置方向

javascript - Python 和 JavaScript 基本通信

javascript - 如何将折线添加到 mapbox.js map ?

r - 将元素添加到 R 中的 data.frames 命名列表

r - 有没有办法让 R 帮助提示(带 Tab)包括某些功能的所有参数的描述(如 Java Doc)?

firefox - 传单瓷砖线条可见

javascript - 传单 geojson 搜索和缩放

android - 如果我最小化我的应用程序或关闭屏幕(谷歌地图),折线将无法正常工作

flutter - 如何在谷歌地图 flutter 中使折线适合街道曲线?