2017-05-25 53 views
2

我正在使用R,RStudio和leaflet包來可視化地圖。從傳單中獲取包裝盒R

我想獲得傳單對象邊界框的最小和最大經緯度。我認爲這可以使用Shiny完成(通過使用類似input$mapobj_bounds的東西),但是有沒有一種非閃亮的方法來做到這一點。

m <- leaflet(width=500,height=400) %>% 
    addTiles() %>% 
    setView(lng = -0.106831, lat = 51.515328, zoom = 18) %>% 
    addCircleMarkers(lng = -0.106831, lat = 51.515328) 

我需要的是一個函數來獲取使用輸入參數m的邊界框。

可以這樣做嗎?

另外,查看對象m時的參數值看起來不正確。

例如

> m$x$limits 
$lat 
[1] 51.51533 51.51533 

$lng 
[1] -0.106831 -0.106831 

編輯

我認爲javascript函數map.getBounds()可能會有所幫助在這裏......這裏(Get the bounding box of the visible leaflet map?)的建議,但不知道如何將其應用到我們的問題。任何幫助,將不勝感激。

+0

是的,我也在一小時前發佈了一個帶'map.getBounds()'的解決方案,但刪除了它,因爲我沒有找到一種方法將值作爲R變量返回。我只設法產生彈出窗口:)如果你喜歡,我可以取消刪除它。關於函數f(m)將邊界返回給R,我認爲人們需要縮放比例的比例尺度,就像谷歌地圖中存在的那樣:https://gis.stackexchange.com/questions/7430/what-比尺度-DO-谷歌-地圖變焦水平-對應到。但我沒有找到它的小冊子,.. – BigDataScientist

+0

一旦對象已被保存,他們可以寫入csv作爲html的輸出?但是,請不要刪除答案,因爲我會熱衷於學習更多javascript。 –

+0

map.getBounds()的結果(由@BigDataScientist很好地演示)會在您調整Viewer窗口大小時發生變化。這表明邊界框並不完全依賴於你的'm'對象。即使你能夠從html輸出結果,它也只會給你這個特定瀏覽器的結果,它是設置。 –

回答

2

這裏是一個javscript版本(初始解決方法)。有關更好的版本,請參閱下文。

leaflet() %>% addTiles() %>% 
    setView(lng = -0.106831, lat = 51.515328, zoom = 18) %>% 
    addEasyButton(easyButton(
    states = list(
     easyButtonState(
     stateName="unfrozen-markers", 
     icon="ion-toggle", 
     title="Get Bounding box", 
     onClick = JS(" 
        function(btn, map) { 
         alert(map.getBounds().getEast()); 
         alert(map.getBounds().getWest()); 
         alert(map.getBounds().getNorth()); 
         alert(map.getBounds().getSouth()); 
        }") 
    ) 
    ) 
) 
) 

編輯:

如果你適應Jeremys回答一點,你可以真正做到這一點沒有的JavaScript。

getBox <- function(m){ 
    view <- m$x$setView 
    lat <- view[[1]][1] 
    lng <- view[[1]][2] 
    zoom <- view[[2]] 
    zoom_width <- 360/2^zoom 
    lng_width <- m$width/256 * zoom_width 
    lat_height <- m$height/256 * zoom_width 
    return(c(lng - lng_width/2, lng + lng_width/2, lat - lat_height/2, lat + lat_height/2)) 
} 
getBox(m) 
2

感謝@ BigDataScientist對指出的答案,該寬度&高度可用!

只要您知道小葉小部件的尺寸,就可以計算邊界框。見leafletjs.com/examples/zoom-levels

鑑於這是與leaflet(width=500,height=400)指定,這將工作。

if (is.null(m$width) | is.null(m$height)) { 
    print("Leaflet width and height must be speciied") 
} else { 
     width <- m$width 
     height <- m$height 
     zoom <- m$x$setView[[2]] 
     lng <- m$x$setView[[1]][2] 
     lat <- m$x$setView[[1]][1] 
     lng_width <- 360 * width/2^(zoom + 8) 
     lng_east <- lng - lng_width/2 
     lng_west <- lng + lng_width/2 
     lat_height <- 360 * height * cos(lat/180 * pi)/2^(zoom + 8) 
     lat_north <- lat + lat_height/2 
     lat_south <- lat - lat_height/2 
} 

> lng_east 
[1] -0.1081721 
> lng_west 
[1] -0.1054899 
> lat_north 
[1] 51.516 
> lat_south 
[1] 51.51466 

相較於@BigDataScientist,這給出了相同的答案map.getBounds到小數點後3位。

enter image description here

編輯 我根據我的回答從單張所引用的文件上。看起來這是一種簡化。我添加了cos(lat/180 * pi)這個術語,可以提高準確性。例如,這現在給出了51.516的北邊界,這與傳單的51.51599707之間的差值僅爲0.0000029。

我已經在幾個不同的緯度和變焦範圍內測試過了。在較低的縮放級別下準確度會降低。

+0

您可以使用m $ height和m $ width給出問題中的m。如果不清楚,請參閱我的帖子中的修改。隨意添加到您的答案,你是一個令人難以置信的接近:) – BigDataScientist

+0

感謝您指出這一點。我很癡迷於查找查看器窗格的尺寸,我錯過了原始問題中指定的單張寬度和高度! –

+0

它也花了我一段時間,因爲我製作了自己的小單張地圖進行測試,並沒有在那裏指定寬度和長度。 – BigDataScientist