2016-05-30 17 views
5

Sto pianificando un grande lat-long NetCDF raster su una mappa R leaflet utilizzando shinydashboard. Quando clicco sulla mappa, viene visualizzato un popup che mostra la riga, la colonna, la posizione lat-lon e il valore del punto raster cliccato. (Vedere il codice riproducibile di seguito)Identificare la posizione di un clic su un raster in volantino, in R

Il problema è che sto sperimentando uno spostamento nel raster se il raster è abbastanza grande. Ad esempio, qui ho fatto clic su un punto che dovrebbe avere un valore, ma il risultato è che il punto identificato è quello sopra.

enter image description here

Credo che questo abbia a che fare con il fatto che la trama utilizzata da leaflet viene proiettata, mentre i dati grezzi che utilizzo per individuare i punti è Lat-Lon, poiché il punto cliccato viene restituito come Lat -Lon da leaflet. Non riesco a utilizzare il file proiettato (depth) poiché le sue unità sono espresse in metri, non in gradi! Anche se ho provato a riproiettare quei metri in gradi, ho ottenuto un turno.

Ecco un esempio eseguibile base del codice:

#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)) 

Come posso identificare correttamente i punti, se il raster è grande?

EDIT: Ho anche voluto fornire alcuni link aggiuntivi per (forse) relative domande di documentazione o di:

+1

Ah! Penso di averlo fatto riprogettando di nuovo i dati dei clic. Sperimenterò quindi postare una risposta. – AF7

risposta

2

I l'ho trovato Posso riproiettare la posizione X-Y (lon-lat) data da input$map_click. In questo caso ho presupposto che la proiezione di input fosse Lon-Lat, ma penso che non sia necessariamente necessario. Ha solo bisogno di avere unità Lat-Lon.

#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 [email protected] +wktext +no_defs" 
#Note that for some reason "[email protected] +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 
Problemi correlati