This is certainly not the intended purpose of mapedit
, but I thought it would be fun to use some accumulated R knowledge to use mapedit
and leaflet
to edit an igraph
layout. To run the code, make sure to run the edit_map
and Shiny
parts separately.
library(igraph)
library(leaflet)
library(mapedit)
karate <- graph.famous("Zachary")
igrf_layout <- layout.auto(karate)
# see a default plot with our layout
plot(karate, layout=igrf_layout)
# plot with leaflet
lf <- leaflet(
igrf_layout,
options = leafletOptions(
crs = leafletCRS(crsClass = "L.CRS.Simple")
)
) %>%
addCircleMarkers(group = "network")
new_layout <- lf %>%
edit_map("network")
# this gets real tricky
# but we will find a much easier way in mapedit
# eventually
library(shiny)
shinyApp(
htmlwidgets::onRender(
lf,
"
function(el,x) {
var lf = this;
setTimeout(
function(){
Shiny.onInputChange(
'getpoints',
Object.keys(lf.layerManager.getLayerGroup('network')._layers)
)
},
500
)
}
"
),
function(input, output) {
observeEvent(input$getpoints, {leafids <<- input$getpoints})
}
)
# now use our hacked method of id retrieval to identify points
library(dplyr)
library(purrr)
layout_df <- data.frame(igrf_layout) %>%
mutate(leafid = leafids) %>%
left_join(
map_df(
new_layout$edited[[1]]$features,
~data.frame(
"leafid" = as.character(.x$properties["_leaflet_id"]),
"newx" = .x$geometry$coordinates[[1]],
"newy" = .x$geometry$coordinates[[2]],
stringsAsFactors = FALSE
)
) %>%
set_names(c("leafid", "newx", "newy"))
)
layout_df <- layout_df %>%
mutate(X1 = ifelse(is.na(newx),X1,newx)) %>%
mutate(X2 = ifelse(is.na(newy), X2, newy))
plot(karate, layout=data.matrix(layout_df[,1:2]))
I'm really interested in getting this cross over working.
Here I build a graph from an sf object using a "common form" data structure. The PRIMITIVE function decomposes simple features into edges based on the paths the standard uses.
This is a simple polygon layer, the first feature has two disconnected paths (a polygon with a hole), the second is a simple polygon that shares a single edge with the first.
In
sc
primitives form, we already have the indexes of the vertices and the edges identified. (Efficient unique ID management is on the todo list ...)The
segment
table of the primitives is already the right form forigraph
, with a minor renaming. In this form we can pull out the topology in pure form and work with it.(The hierarchy in the sc tables keeps track of the higher levels of grouping so we could pull out the edges and "do stuff").
Ultimately, I think we can bring this topology structure up to the user level, so that we can provide finely honed editing and interactivity.
(Thanks!)