2016-05-30 14 views
5

Ich zeichne eine große Lat-lon NetCDF raster über eine R leaflet Karte mit shinydashboard. Wenn ich auf die Karte klicke, erscheint ein Popup-Fenster, in dem Zeile, Spalte, Breitengrad und Wert des angeklickten Rasterpunkts angezeigt werden. (Siehe reproduzierbaren Code unten)Identifizieren Sie die Position eines Klick auf ein Raster in Prospekt, in R

Das Problem ist, dass ich eine Verschiebung im Raster erfahre, wenn das Raster groß genug ist. Zum Beispiel habe ich hier auf einen Punkt geklickt, der einen Wert haben sollte, aber das Ergebnis ist, dass der identifizierte Punkt der obige ist.

enter image description here

Ich glaube, dies mit der Tatsache zu tun, dass das Raster von leaflet verwendet wird projiziert, während die Rohdaten ich die Punkte zu identifizieren, verwenden Lat-Lon ist, da der angeklickten Punkt als Lat zurückgegeben -Lon von leaflet. Ich kann die projizierte Datei (depth) nicht verwenden, da ihre Einheiten in Metern und nicht in Grad angegeben sind! Selbst wenn ich versuchte, diese Meter auf Grad umzustellen, bekam ich eine Verschiebung.

Hier ist ein grundlegendes runnable Beispiel für den 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)) 

Wie kann ich die Punkte korrekt identifizieren, wenn das Raster groß ist?

EDIT: Ich wollte auch einige zusätzliche Links zu (möglicherweise) die zugehörige Dokumentation oder Fragen geben:

+1

Ah! Ich denke, ich habe es geschafft, die Click-Daten erneut zu projizieren. Ich werde experimentieren und dann eine Antwort posten. – AF7

Antwort

2

I habe das gefunden Ich kann die durch input$map_click gegebene X-Y (lon-lat) -Position zurückprojizieren. In diesem Fall habe ich die Eingabe-Projektion als Lon-Lat angenommen, aber ich denke, dass es nicht unbedingt sein muss. Es muss nur Lat-Lon-Einheiten haben.

#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