Skip to content

Commit

Permalink
Start of editing of points on the map
Browse files Browse the repository at this point in the history
  • Loading branch information
gistin authored and barnabywalker committed Feb 9, 2023
1 parent 319e277 commit fed2877
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 44 deletions.
25 changes: 16 additions & 9 deletions JM_notes
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,32 @@ WORK DONE

#udpated POWO search to trap when you have no results, ugly but works
#tweak map size to be same as left panel

WORK NEEDED
HIGH
# User editable, moveable, delete point etc
#180 date line delt with for EOO, AOO not that useful
#Suggest Rating for EOO and AOO added
#Projection details stored for use later
#updated so that data progresses through to map
#updated so default fields are build etc as below
# a. geocat_id = an internal ID which is populated on import (ie 1:nrow), new points will be added to this with a nrow + _leaflet_id (_leaflet_id is a unique number from leaflet) this should allow me to use this id to query all on map edits/delete. The reason for odd allocation is that leaflet assigns its own unique values and I can’t find a way to update (read only), there is a possibility of a clash if, I just increment ID and I may have get back out the leaflet ID as some point (not sure I do). I may simplify this later.
#b. geo_status = a record of what has happen to a point ie “new point”, “moved point”, “deleted point”
#c. geocat_use = Flag to false it point is deleted (could query on above, but I feel this is quicker)?
#d. geocat_analysis = Flag for any queries (ie GBIF only etc), which we can switch on or off depending on reactive # elements (ie your switches for GBIF/user)

#GBIF query

WORK NEEDED
HIGH
# User editable, moveable, delete point etc
# GBIF query

MEDIUM
#Split polygon when over date line
# add suggestted IUCN ratings linked to EOO and AOO values
# return the projection used to the user?
#colour points by data_source
#report Projection
#report metadata (ie projection, GBIF query and citations etc)
# colour points by data_source
# TDWG maps from species name

LOW
# POWO search which returns nothing, need to inform user in the information box to the left (where steve reports missing values)
# POWO search clear off old searches (maybe a button)
# Map to reproduce over date line (ie not say map data not available)
# split aoo over dateline (not going to happen very often)
# allow data with long 180++

120 changes: 85 additions & 35 deletions R/app.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ geocatApp <- function(...) {
ui <- fluidPage(

shinyjs::useShinyjs(),

tags$html(lang = "en"),

# title
Expand Down Expand Up @@ -80,7 +80,7 @@ geocatApp <- function(...) {
column(
12,
align = "centre",
shiny::helpText("Upload a CSV with a unique 'id' and 'longitude', 'latitude' fields "),
shiny::helpText("Upload a CSV with at least 'longitude', 'latitude' fields "),
shiny::fileInput(
"csv_in",
NULL,
Expand Down Expand Up @@ -152,9 +152,12 @@ geocatApp <- function(...) {

##### server #####
server <- function(input, output, session) {
#JM builds an empty df to populate later
################################
values <- reactiveValues(
analysis_data=empty_tbl_()
)
values$analysis_data <- buildspdf()

observeEvent(input$reset, {
session$reload()
Expand All @@ -168,21 +171,27 @@ server <- function(input, output, session) {
} else {
shiny::validate("Invalid file; please upload a .csv file")
}

shiny::validate(check_fields_(data, c("longitude", "latitude", "id")))
###########################################################
#ID not needed any more
#shiny::validate(check_fields_(data, c("longitude", "latitude","id")))
shiny::validate(check_numeric_(data, c("longitude", "latitude")))

values$analysis_data <-
dplyr::bind_rows(
values$analysis_data,
data %>%

csv_imported <- data %>%
dplyr::select(longitude,latitude, id) %>%
dplyr::filter(if_all(everything(), ~!is.na(.))) %>%
dplyr::filter(longitude < 180, longitude > -180,
latitude < 90, latitude > -90) %>%
dplyr::mutate(group="csv")
dplyr::mutate(
geocat_id=seq.int(nrow(values$analysis_data)),
geocat_source="csv import",
)

values$analysis_data <-
dplyr::bind_rows(
values$analysis_data,
csv_imported
)

data
})

Expand Down Expand Up @@ -210,7 +219,7 @@ server <- function(input, output, session) {

leaflet::setView(lng = 0,
lat = 0,
zoom = 2) %>%
zoom = 3) %>%

leaflet.extras::addSearchOSM(options = leaflet.extras::searchOptions(
autoCollapse = F,
Expand All @@ -220,7 +229,28 @@ server <- function(input, output, session) {
)) %>%

leaflet::addScaleBar(position = "bottomright") %>%

######################################################
#JM
#df <- values$analysis_data
leaflet.extras::addDrawToolbar(editOptions = editToolbarOptions(edit=TRUE),
targetGroup = 'mappoints',
circleMarkerOptions=FALSE,
rectangleOptions=FALSE,
circleOptions=FALSE,
polygonOptions=FALSE,
polylineOptions=FALSE) %>%

leaflet::addCircleMarkers(data = values$analysis_data[values$analysis_data$geocat_use==TRUE,],
popup = "popup",#~thetext,
layerId = ~geocat_id,
group="mappoints",
radius = 7,
color="#FFFFFF",
stroke = T,
fillColor = "#FF0000",
fillOpacity = 1,
options = markerOptions(draggable = FALSE)) %>%
#####################################################
leaflet::addMeasure(
position = "bottomleft",
primaryLengthUnit = "meters",
Expand All @@ -236,12 +266,6 @@ server <- function(input, output, session) {
options = leaflet::providerTileOptions(noWrap = TRUE)
) %>%

leaflet::addProviderTiles(
provider = "Esri.WorldStreetMap",
group = "ESRI Open Street map",
options = leaflet::providerTileOptions(noWrap = TRUE)
) %>%

leaflet::addProviderTiles(
provider = "OpenStreetMap.Mapnik",
group = "Open Street Map",
Expand All @@ -258,33 +282,32 @@ server <- function(input, output, session) {
baseGroups = c(
"ESRI World Imagery",
"Open Street Map",
"Open Topo Map",
"ESRI Open Street map"
"Open Topo Map"
),
options = leaflet::layersControlOptions(collapsed = FALSE)
)
})

output$csvValidation <- shiny::renderPrint({

shiny::observeEvent(input$leafmap_draw_new_feature, {
print("New Feature added")
})

output$validation <- shiny::renderPrint({
data <- csvpointsInput()
if (! is.data.frame(data)) {
data
}
msg <- c(
check_complete_(data, c("longitude", "latitude", "id")),
check_range_(data, "longitude", -180, 180),
check_range_(data, "latitude", -90, 90),
#check_complete_(data, c("longitude", "latitude", "id")),
#check_range_(data, "longitude", -180, 180),
#check_range_(data, "latitude", -90, 90),
check_rounded_(data, "longitude"),
check_rounded_(data, "latitude"),
check_zeros_(data, "longitude"),
check_zeros_(data, "latitude")
)

if (! is.null(msg)) {
msg
}
})

output$gbifValidation <- shiny::renderPrint({
data <- gbifPointsInput()
if (nrow(data) == 0) {
Expand Down Expand Up @@ -325,7 +348,9 @@ server <- function(input, output, session) {

shiny::observeEvent(input$csv_in, {

df <- csvpointsInput()
df <- values$analysis_data
#needs cleaning up with formating and maybe more information
popuptext <- paste(df$geocat_id,df$sci_name,df$latitude,df$longitude)

leaflet::leafletProxy("mymap", data=df) %>%

Expand All @@ -341,7 +366,7 @@ server <- function(input, output, session) {
fillOpacity = 1,
fill = T,
fillColor = "#0070ff",
popup = as.character(df$id))
popup = as.character(popuptext))
})

shiny::observeEvent(input$queryGBIF, {
Expand Down Expand Up @@ -444,8 +469,33 @@ server <- function(input, output, session) {

shiny::observeEvent(list(input$Analysis, values$eoo_polygon, values$aoo_polygon), {
if (input$Analysis){
leaflet::leafletProxy("mymap", data=values$aoo_polygon) %>%
leaflet::clearGroup("AOOpolys") %>%
#analysis here
#print(values$analysis_data)
d <- data.frame(long=values$analysis_data$longitude,lat=values$analysis_data$latitude)
# if (!input$gbif_onoff) {
# d <- dplyr::filter(d, source != "gbif")
# }
#if (!input$csv_onoff) {
# d <- dplyr::filter(d, source != "csv")
#}
if (nrow(d) == 0) {
return()
}
#d <- dplyr::select(d, -source)#is this needed or is it the above needed, I think they are doing the same thing
#JMJJMJMJMJM
#project the data so we can work on it in a sensible space for areas and distance
projp <- simProjWiz(d)
#reports projection need to sent this to validate
#
print (projp$crs)
EOO <- eoosh(projp$p)
AOO <- aoosh(projp$p)
values$eooarea <- EOO$area
values$aooarea <- AOO$area
values$eoo_rat <- ratingEoo(EOO$area,abb=TRUE)
values$aoo_rat <- ratingAoo(AOO$area,abb=TRUE)
#JMJMJMMJ
leaflet::leafletProxy("mymap",data = AOO$polysf) %>%
leaflet::addPolygons(
color = "#000000",
stroke = T,
Expand Down
48 changes: 48 additions & 0 deletions R/validate-data.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,51 @@
#Function to setup empty dataframe for geoCAT to work with
#JM
#notes
#geocat_source = where the data has come from (ie gbif, csv import, user defined)
#geocat_id = an internal ID which is populated on import (ie 1:nrow), new points will be added to this with a nrow + _leaflet_id (_leaflet_id is a unique number from leaflet) this should allow me to use this id to query all on map edits/delete. The reason for odd allocation is that leaflet assigns its own unique values and I can’t find a way to update (read only), there is a possibility of a clash if, I just increment ID and I may have get back out the leaflet ID as some point (not sure I do). I may simplify this later.
#geocat_status = a record of what has happen to a point ie “new point”, “moved point”, “deleted point”
#geocat_use = Flag to false it point is deleted (could query on above, but I feel this is quicker)?
#geocat_analysis = Flag for any queries (ie GBIF only etc), which we can switch on or off depending on reactive # elements (ie your switches for GBIF/user)
#geocat_notes = records what has happened the points when moved (ie moved from x,y to p,q)
#note at this point #geocat_analysis is not used
buildspdf <- function(){
df <- data.frame(BasisOfRec = as.character(),
EVENT_YEAR = as.integer(),
latitude = as.numeric(),
longitude = as.numeric(),
sci_name = as.character(),
PRESENCE = as.integer(),
ORIGIN = as.integer(),
SEASONAL = as.integer(),
CATALOG_NO = as.character(),
SPATIALREF = as.character(),
CITATION = as.character(),
COMPILER = as.character(),
recordno = as.character(),
recordedBy = as.character(),
yrcompiled = as.integer(),
DATA_SENS = as.logical(),
SOURCE = as.logical(),
dist_comm = as.logical(),
tax_comm = as.logical(),
#user specific
id = as.integer(),
#geocat specific fields
geocat_source = as.character(),
geocat_id = as.integer(),
geocat_status = as.character(),
geocat_use = as.logical(),
geocat_analysis = as.logical(),
geocat_notes = as.character()
)
#add some dummy data
mypoints <- data.frame(longitude = rnorm(4) + 46, latitude = rnorm(4) + -21, geocat_id = c(1:4),geocat_use=TRUE)
merge(df,mypoints, all=TRUE)


}


# Functions to validate occurrences and occurrence files

check_fields_ <- function(df, required_fields) {
Expand Down
1 change: 1 addition & 0 deletions app.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
library(shiny)
library(leaflet.extras)
pkgload::load_all(".")
geocatApp()

0 comments on commit fed2877

Please sign in to comment.