Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add layerIds to drawn polygons/circles from leaflet draw plugin? #77

Open
lauren-oldham opened this issue May 5, 2017 · 12 comments
Labels

Comments

@lauren-oldham
Copy link

lauren-oldham commented May 5, 2017

I've read a similar question here, but I don't think that it is applicable to my situation.

I just want to know how to assign layerIds to different shapes as a I draw them with the addDrawToolbar functionality. Here's a minimal example:

library(shiny)
library(leaflet)
library(leaflet.extras)

lngs <- c(20, 23, 23)
lats <- c(21, 20, 24)

shinyApp(
  ui <- leafletOutput("map"), 
  
  server <- function(input, output, session){
    
    output$map <- renderLeaflet({
      leaflet() %>% 
        addTiles() %>% 
        addCircleMarkers(lng = lngs, lat = lats, layerId = 1:length(lats)) %>% 
        addDrawToolbar(targetGroup = "test", 
                       rectangleOptions = F, 
                       polylineOptions = F, 
                       markerOptions = F, 
                       editOptions = editToolbarOptions(selectedPathOptions = selectedPathOptions()), 
                       circleOptions = drawCircleOptions(shapeOptions = drawShapeOptions(clickable = T)))
    })  # END RENDER LEAFLET 
    
    observeEvent(input$map_marker_click, {
      print(input$map_marker_click)
    })  
    
    observeEvent(input$map_draw_new_feature, {
      print(input$map_draw_new_feature)
    })

})

So I have a map with various points plotted. Each point has its own layerId. The idea is to allow users to draw circles/shapes over the points that they want selected. I can then subset the points layer by the drawn polygon layer. To do this, I need to assign layerIds to the polygons as they're drawn. How do I accomplish this? I see that with input$map_draw_new_feature, I can access input$map_draw_new_feature$properties$_leaflet_id``, but it appears that this value is randomly assigned, so I don't know how to access it. I've also made clickable = T, but the object does not appear with `input$map_shape_click`, nor `input$map_marker_click`.

@bhaskarvk
Copy link
Contributor

This is a chicken and egg problem is it not? You can't assign IDs to polygons that are not drawn yet, and you can't use the randomly assigned IDs once they are drawn.
FWIW even if the IDs are randomly assigned, they stick, that is once a drawn polygon/circle/point has been assigned an ID, that ID remains the same as long as you don't deleted the shape/point. So you can be sure to receive the same ID back once the polygon is drawn and subsequently edited.

About the clickable part, for the drawn polygons I don't emit those shiny events like regular added shapes. That's something I can easily do, but as things stand now it's not implemented.

Lastly if all you want is the ability to select points, look at leaflet::addSelection() https://github.com/rstudio/leaflet/blob/master/R/selection.R

@jamiemkass
Copy link

I am also interested in retrieving the coordinates of drawn polygons to use in overlay operations on points. The addSelection() function does not seem to be part of the newest release of leaflet on CRAN.

Following @lauren-oldham 's code, it seems that input$map_draw_new_feature retrieves the geoJSON for the drawn polygon. I searched but cannot find anywhere an explanation of all the options for input$... related to the draw toolbar. Is there a resource somewhere? Thanks a lot.

@lauren-oldham
Copy link
Author

@ndimhypervol Here is a list of the draw events. Is this what you mean?

@jamiemkass
Copy link

jamiemkass commented Jul 17, 2017

@lauren-oldham, yes, thank you! I was also able to extract the coordinates via that new feature event. Then it's just a matter of bundling the coordinates into a SpatialPolygon and performing over() on the points. I think that solves my problem. Any luck with the assigning unique layerIDs to polys? I am also interested in using multiple polys for selection.

@lauren-oldham
Copy link
Author

lauren-oldham commented Jul 17, 2017

@ndimhypervol No luck with layerIds. I actually did the same method you mentioned above! Extracted coordinates of the drawn polygon converted to SPDF, then used over(). So you want to draw multiple polygons to select more points?

@ngfrey
Copy link

ngfrey commented Aug 1, 2017

@lauren-oldham With regard to adding multiple polygons: Could you maybe do that by saving the input$map_draw_new_feature stuff into a reactiveValues() list? Then doing the same bundling of coordinates into a SpatialPolygon, using over() inside an lapply or sapply statement? I haven't coded the logic yet, so I may be off base here.

Also @bhaskarvk to your chicken and egg comment about leaflet id's for polygons..this is a total hack, but could you observe the new leaflet draw event, append all the data to a reactiveValues() list, remove the object from the map, then redraw it while specifying a desired id? It's a hack because you're drawing, collecting, removing, then drawing the same object again, but it would get you the polygon with whatever id you want...

@lauren-oldham
Copy link
Author

@ngfrey That's essentially the solution that I ended up using for what I needed!

@bhaskarvk
Copy link
Contributor

I need to think about this. I will work on this over the weekend. Thanks for all your comments. They are super useful.

@lauren-oldham
Copy link
Author

@bhaskarvk I actually created a workaround to assign layerIds to drawn polygons, although in a different context than my original question. The long and short of it is:

  1. Create reactive list of SpatialPolygons as they are drawn (converting based on the drawn coordinates) with input$map_draw_new_feature
  2. Observing input$map_draw_stop, a text input box is displayed, prompting the user to label their polygon, which is saved in a reactive context
  3. Labels are appended in a data frame based on aforementioned indexing (length of reactive list)
  4. An action button is employed to "finalize" polygons by creating a SpatialPolygonsDataFrame, which combines the reactive SpatialPolygons and the created data frame with labels.

You can then use leafletProxy() to remove the drawn polygons and plot the same shapes as a single SPDF with labels, layerIds, etc. Hope this makes sense. I'm sure there are other more elegant solutions, but the point that I'm trying to make is that it's totally possible to assign layerIds after polygons are drawn. :)

@ngfrey
Copy link

ngfrey commented Aug 15, 2017

@lauren-oldham Hey! Thinking about this more, you should draw the polygons with the ids you want BEFORE removing the polygons with the leaflet created ids. That way the user ideally never knows that something happened. It would prevent the shape from flashing on the screen.

@lauren-oldham
Copy link
Author

@ngfrey This is not the project that I'm currently working on anymore, but I made a quick little video of where I had left things off with the polygon drawing tool: https://www.screencast.com/t/16rrNV6Hel

It's still a bit quirky, but I think that I got the hardest part down, which is assigning ids to the drawn polygons. In its current format, you draw a polygon, and then a dialog opens (similar to QGIS) for you to label that polygon. You manually hit submit, then can continue to draw and label as many polygons as you want. Each new polygon is blue and unlabeled until you click the button to finalize your polygons, when then converts all of the polygons into an Spatial Polygons Data Frame. It's that finalization of polygons that removes the initial blue polygons and replots the colored SPDFs.

Again, lots of quirks still here. You are able to create multipolygons by using the same label for separate polygons, but that might not be clear based on what I've got now. Furthermore, (at the moment) there is no way of telling the difference between polygons that you've drawn but haven't yet finalized. Also doesn't allow editing of polygons as they're being drawn. All things that I plan to tackle once I get back to the project, but I'm not there at the moment. :)

@bhaskarvk
Copy link
Contributor

Unfortunately I am currently very busy with day jb + other personal things to tackle this. I will revisit this sometime next month.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants