在R中标识单击传单中的栅格的位置 [英] Identify position of a click on a raster in leaflet, in R

查看:85
本文介绍了在R中标识单击传单中的栅格的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用shinydashboard在R leaflet图上绘制大型latNet NetCDF raster.当我单击地图时,会弹出一个窗口,并显示行,列,纬度位置和所单击的栅格点的值. (请参见下面的可复制代码)

I am plotting a large lat-lon NetCDF raster over an R leaflet map using shinydashboard. When I click on the map, a popup comes out and shows row, column, lat-lon position and value of the clicked raster point. (See reproducible code below)

问题是,如果栅格足够大,我正在经历栅格的移动.例如,在这里我单击了一个应该具有值的点,但是结果是所识别的点是上面的那个点.

The problem is that I am experiencing a shift in the raster if the raster is large enough. For example, here I clicked on a point which should have a value, but the result is that the identified point is the one above.

我认为这与以下事实有关:投影了leaflet使用的栅格,而我用来识别点的原始数据是Lat-Lon,因为单击的点由<返回为Lat-Lon c1>.我无法使用投影文件(depth),因为其单位是米,而不是度! 即使我尝试将那些米重新投影到度,我也得到了转变.

I believe this has to do with the fact that the raster used by leaflet is projected, while the raw data I use to identify the points is Lat-Lon, since the clicked point is returned as Lat-Lon by leaflet. I cannot use the projected file (depth) since its units are in meters, not degrees! Even if I tried to reproject those meters to degrees, I got a shift.

以下是该代码的基本可运行示例:

Here is a basic runnable example of the code:

#Libraries
library(leaflet)
library(raster)
library(shinydashboard)
library(shiny)

#Input data
download.file("https://www.dropbox.com/s/y9ekjod2pt09rvv/test.nc?dl=0", destfile="test.nc")
inputFile    = "test.nc"
inputVarName = "Depth"
lldepth <- raster(inputFile, varname=inputVarName)
lldepth[Which(lldepth<=0, cells=T)] <- NA #Set all cells <=0 to NA
ext <- extent(lldepth)
resol <- res(lldepth)
projection(lldepth) <- "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"

#Project for leaflet
depth <- projectRasterForLeaflet(lldepth)

#Prepare UI
sbwidth=200
sidebar <- dashboardSidebar(width=sbwidth)
body <- dashboardBody(
          box( #https://stackoverflow.com/questions/31278938/how-can-i-make-my-shiny-leafletoutput-have-height-100-while-inside-a-navbarpa
            div(class="outer",width = NULL, solidHeader = TRUE, tags$style(type = "text/css", paste0(".outer {position: fixed; top: 50px; left: ", sbwidth, "px; right: 0; bottom: 0px; overflow: hidden; padding: 0}")),
            leafletOutput("map", width = "100%", height = "100%")
            )
          )
        )
ui <- dashboardPage(
  dashboardHeader(title = "A title"),
  sidebar,
  body
)
#
#Server instance
server <- function(input, output, session) {
  output$map <- renderLeaflet({#Set extent
    leaflet()  %>%
      fitBounds(ext[1], ext[3], ext[2], ext[4])
  })

  observe({#Observer to show Popups on click
    click <- input$map_click
    if (!is.null(click)) {
      showpos(x=click$lng, y=click$lat)
    }
  })

  showpos <- function(x=NULL, y=NULL) {#Show popup on clicks
    #Translate Lat-Lon to cell number using the unprojected raster
    #This is because the projected raster is not in degrees, we cannot use it!
    cell <- cellFromXY(lldepth, c(x, y))
    if (!is.na(cell)) {#If the click is inside the raster...
      xy <- xyFromCell(lldepth, cell) #Get the center of the cell
      x <- xy[1]
      y <- xy[2]
      #Get row and column, to print later
      rc <- rowColFromCell(lldepth, cell)
      #Get value of the given cell
      val = depth[cell]
      content <- paste0("X=",rc[2],
                        "; Y=",rc[1],
                        "; Lon=", round(x, 5),
                        "; Lat=", round(y, 5),
                        "; Depth=", round(val, 1), " m")
      proxy <- leafletProxy("map")
      #add Popup
      proxy %>% clearPopups() %>% addPopups(x, y, popup = content)
      #add rectangles for testing
      proxy %>% clearShapes() %>% addRectangles(x-resol[1]/2, y-resol[2]/2, x+resol[1]/2, y+resol[2]/2)
    }
  }

  #Plot the raster
  leafletProxy("map") %>%
    addRasterImage(depth, opacity=0.8, project=FALSE, group="Example", layerId="Example", colors=colorNumeric(terrain.colors(10), values(depth), na.color = "black"))
}


print(shinyApp(ui, server))

如果栅格很大,如何正确识别点?

How can I correctly identify the points, if the raster is large?

我还想提供一些其他链接,以指向(可能)相关的文档或问题:

I also wanted to provide some additional links to (possibly) related documentation or questions:

  • Raster image seems to be shifted using leaflet for R
  • R for leaflet redirect when clicking on raster image
  • https://gis.stackexchange.com/questions/183918/is-it-possible-to-use-a-rasterclick-event-within-an-interactive-leaflet-map
  • marker mouse click event in R leaflet for shiny

推荐答案

我发现我可以将input$map_click给出的X-Y(lon-lat)位置重新投影回去. 在这种情况下,我假设输入投影为Lon-Lat,但我认为不一定必须如此.它只需要有Lat-Lon单位.

I have found that I can reproject back the X-Y (lon-lat) position given by input$map_click. In this case I assumed the input projection to be Lon-Lat, but I think it doesn't necessarily have to be. It just needs to have Lat-Lon units.

#Set projections
inputProj <- "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"
leafletProj <- "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +units=m +nadgrids=@null +wktext +no_defs"
#Note that for some reason "+nadgrids=@null +wktext" is very important
  #as hinted to by other questions and answers linked in my question.
xy <- SpatialPoints(data.frame(x,y))
proj4string(xy) <- inputProj
xy <- as.data.frame(spTransform(xy, leafletProj))
#Get the cell number from the newly transformed metric X and Y.
cell <- cellFromXY(depth, c(xy$x, xy$y))

#At this point, you can also retrace back the center of the cell in
  #leaflet coordinates, starting from the cell number!
xy <- SpatialPoints(xyFromCell(depth, cell))
proj4string(xy) <- leafletProj
xy <- as.data.frame(spTransform(xy, inputProj))
#Here XY will again be in lat-lon, if you projection says so,
  #indicating the center of the clicked cell

这篇关于在R中标识单击传单中的栅格的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆