簡體   English   中英

傳單折線不越過日期變更線傳單

[英]Leaflet Polylines do not go over date line Leaflet

對於 Shiny uni 項目,我面臨着跨越太平洋日期變更線的折線問題。 從一個中心(武漢)我想創建 72 條線,顯示它們連接不同地區。 我已經創建了一個循環,以確保 Longitudes > 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

輸出閃亮

有幾件事你可以嘗試。 一種是使用breakAtDateLine = TRUE在選項gcIntermediate

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
  )

如您所見,它打破了線條,但在屏幕左側繼續它,這並不理想。

在此處輸入圖片說明

我們可以嘗試的另一件事是使用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) 

在此處輸入圖片說明

當它到達地圖頂部時仍然有點奇怪,但希望這是你可以忍受的

我最近在一個儀表板上工作,遇到了同樣的問題。 我提出的解決方案與 Chris 上面的評論有點混合。 區別:

  1. df 列不是創建 p1 和 p2,而是直接在 gcIntermediate 中調用

  2. 保持sp = TbreakAtDateLine = T

  3. 對生成的 sp 對象執行 for 循環,不修改 df 並使用 SpatialLines 進行轉換

    df2 <- gcIntermediate( df[,c(1,2)], df[,c(3,4)], n = 72, addStartEnd = TRUE, sp = T, breakAtDateLine = T) for (l in 1:length(df2@lines)){ if (length(df2@lines[[l]]@Lines) > 1){ df2@lines[[l]]@Lines[[2]]@coords[ ,1] <- df2@lines[[l]]@Lines[[2]]@coords[ ,1] +360 df2@lines[[l]]@Lines[[1]]@coords <- rbind(df2@lines[[l]]@Lines[[1]]@coords, df2@lines[[l]]@Lines[[2]]@coords) df2@lines[[l]]@Lines[[2]] <- NULL } } 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 = df2, weight = 1)

輸出(類似於 Chris 的)該循環利用了這樣一個事實,即gcIntermediate()通常只為不跨越 ante-meridiem 的特征創建一行。 但是當線確實交叉時,它會為特征創建兩條線,負坐標中設置的線始終在列表中排在第二位。 因此,循環查找具有 2 個特征的行,取第二個特征的長度並加上 +360,將第二行坐標綁定到第一行,並將第二行歸零。

這個解決方案做的事情幾乎一樣,而且速度也快不了多少(我做了一個基准測試,針對 Chris 的第二個答案 1000 倍運行這個,這個解決方案平均只快 0.3%)。 但是,它確實減少了代碼、對象混亂和通過轉換處理數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM