crazycapivara / openlayers

An R Interface to OpenLayers
Other
19 stars 3 forks source link

Implementing draw interaction? #21

Open mhaffner opened 5 years ago

mhaffner commented 5 years ago

First, thanks for creating this package! Leaflet for R is great, but Leaflet has always felt limited compared to OpenLayers to me, so it's nice to see that this package available.

Do you have suggestions on how to implement the "draw-features" interaction of OpenLayers here? Of course, it would be wonderful if someone else did it for me, but I would be willing to put some skin in the game with a little direction.

crazycapivara commented 5 years ago

Hi,

until now there was no effort in adding the OL draw features. The interactions should work fine but it would be more effort, if you also want to save what you draw or or pipe it back to R. What will be the use case?

see mapedit

mhaffner commented 5 years ago

@crazycapivara Thanks for your response. I'd like to use this functionality to build a platform for logging user responses and perceptions on spatial data. Then, I want to aggregate the data to help explain some basic techniques of geographic information systems (GIS).

For example, when I talk about perceptual regions of the United States in class, I give students a blank map and ask them to draw a circle around what they consider to be "The Midwest". I then display a few examples in the next class period. I'd like to automate this a bit, aggregate results immediately, etc. So yes, I would like to save the response and pipe back to R for further analysis.

I've read up a bit about the htmlwidgets library as it looks like that's what you're using here. This problem is a small part of a larger project my students and I are working on over the summer, so I can spend some time working on this. Any suggestions would be much appreciated. Are you interested in PRs?

crazycapivara commented 5 years ago

@mhaffner Sounds pretty nice. Yes, PRs are always welcome. It would also be a good start to switch to OL 5 and in a next step use webpack to develop the javascript bindings, so that it is possible to split up the js-bindings into modules making changes a lot easier. At the moment I focus on the deckgl package. Maybe it is also possible to integrate draw features there!?

crazycapivara commented 5 years ago

I think the best way to pipe stuff back to R is using Shiny Gadgets (see also RStudio Add-Ins). That´s the way mapedit does it. Moreover, it could also be a good idea to create an openlayers.extras package extending the openlayers package like leaflet.extras.

mhaffner commented 5 years ago

@crazycapivara Thanks for the info; it's a helpful start. This all might be above me, but I won't know till I try! Deckgl looks awesome by the way - both the js library and your R package for it.

If I do figure out how to implement the draw interaction of OL and R, could you be convinced to license the repo with GPLv3 or MIT? If not, do you have any restrictions on educational/commercial use? At the moment I only have intentions to use this for educational purposes. Just curious.

crazycapivara commented 5 years ago

As you can see in the DESCRIPTION file of the package it is already under the MIT license.

If I have find some time I will try to add the draw functionality.

crazycapivara commented 5 years ago

DESCRIPTION

mhaffner commented 5 years ago

@crazycapivara Gotcha - thanks for clarifying on the license. When I click the license link from the repo, it directs me here.

If you want to add the draw functionality and have the time, by all means please do! But I may be able to direct some funding on this project toward a small bounty or two for things like this. I'll start with trying to implement this myself and see how things go from there.

crazycapivara commented 5 years ago

Hi,

I just added basic draw functionality. You can install it from branch feature/draw via:

devtools::install_github("crazycapivara/openlayers", ref = "feature/draw")

Use draw interaction like this:

ol() %>%
  set_view(zoom = 8) %>%
  add_stamen_tiles() %>%
  add_draw("Circle") # Polygon, Point and LineString are other possible values

In the JavaScript console of the browser you can run the following to get the drawn features:

olWidget.getDrawFeatures()

Next step will be to pipe this back to R.

mhaffner commented 5 years ago

@crazycapivara This is awesome! You're a wizard.

crazycapivara commented 5 years ago

Features are now piped back to R in shiny mode.

I added a shiny gadget to the example folder:

draw-features

Just source the file and then run:

features <- draw_features()

When finished press Done button in your browser and go back to your R console. The drawn features are now accessable as sf object.

See also Shiny draw example where raw features are printed to the R console every time a feature is added.

Features are accessable in Shiny via input$widgetId + _ + draw, so for widgetId = map it will be input$map_draw.

mhaffner commented 5 years ago

Thanks so much for this! Come to FOSS4G in Romania this summer and I'll buy you a beer!

crazycapivara commented 5 years ago

Maybe we will meet there.

mhaffner commented 5 years ago

So I've been doing a little playing around with this, and I can get the Point to work well as the feature is available via map_click back in R. I'm having a little trouble with polygons though. I tried to simplify your example a bit using the following:

library(shiny)
library(miniUI)
library(openlayers)

## shiny gadget
draw_features <- function(draw_type = "Polygon") {

  ## view
  ui <- miniPage(
    gadgetTitleBar("Draw features"),
    miniContentPanel(
      olOutput("map", height = "100%")
    )
  )

  ## controller
  server <- function(input, output, session) {
    output$map <- renderOl({
      ol() %>%
        add_stamen_tiles() %>%
        add_draw(draw_type)
    })

    observeEvent(input$done, {
      features <- input$map_draw

      print(features)
      stopApp(features)
    })
  }

  ## start gadget in browser mode
  runGadget(ui, server, viewer = browserViewer())
}

which is essentially the same thing you had just without the parse_polygons functions (which threw an error, but the error does not have to do with this function). When I source the above script and use

features <- draw_features()

draw a feature in the browser, and click the "Done" button, the R console reads

NULL

I think this is an issue with the input$map_draw variable, which doesn't seem to exist.

crazycapivara commented 5 years ago

Hm, just run your example and get for example:

[1] "[[-7279251.0776539035,-528332.7395071387],[-5557277.7044454515,-1663269.7354854364],[-7044436.526761841,-2563392.1805716716],[-7279251.0776539035,-528332.7395071387]]"

So , I cannot reproduce your NULL error.

Did you install the latest version from branch ref/draw?

Does olWidget.getDrawFeatures() in the JavaScript console of your browser return any features?

crazycapivara commented 5 years ago

ol-draw-features

mhaffner commented 5 years ago

@crazycapivara I tried this on a different machine and got it to work, so it's something on my end. I think it's safe to close this issue now?

crazycapivara commented 5 years ago

Maybe move shiny gadget example to package, so that it can be used out of the box!?

mhaffner commented 4 years ago

Sure, sounds great!