@@ -33,7 +33,7 @@ ui <- page_sidebar(
3333 sidebar = sidebar(
3434 width = 300 ,
3535 card(
36- card_header(" Areas " ),
36+ card_header(" Area selector " ),
3737 radioButtons(
3838 " layer_selection" ,
3939 NULL ,
@@ -56,8 +56,7 @@ ui <- page_sidebar(
5656 card(
5757 card_header(" Biodiversity" ),
5858 chat_ui(" chat" , placeholder = " hummingbirds" ),
59- actionLink(" get_richness" , " get sp richness" ),
60- actionLink(" clear_richness" , " 🧹" )
59+ actionLink(" clear_richness" , " 🧹 clear richness" )
6160 ),
6261
6362 br(),
@@ -104,20 +103,44 @@ server <- function(input, output, session) {
104103 taxa_selections <- taxonomicSelectorServer(" taxa_selector" )
105104
106105 # Dynamic variables:
107- layer_filter <- reactiveVal(NULL )
106+ layer_filter <- reactiveVal(NULL ) # active layer filter (maplibre filter)
107+ taxa_filter <- reactiveVal(NULL ) # active species filter (list)
108+ active_feature <- reactiveVal(NULL ) # active polygon
108109 selected_feature <- reactiveVal(NULL )
109- taxa_filter <- reactiveVal(NULL )
110110
111- observeEvent(input $ chat_user_input , {
112- taxa_selected <- txt_to_taxa(input $ chat_user_input )
113- # print(taxa_selected)
114- taxa_filter(taxa_selected )
115- chat_append(" chat" , " done" )
116- })
111+ # Waterfall strategy to determine feature
112+ get_active_feature <- function (input ) {
113+ gdf <- active_feature()
114+
115+ if (is_empty(gdf )) {
116+ print(" No feature selected, checking for drawing" )
117+ gdf <- get_drawn_features(maplibre_proxy(" map" ))
118+ }
119+ if (is_empty(gdf )) {
120+ print(" No drawing found, checking geocoder" )
121+ gdf <- geocoder_to_gdf(input $ map_geocoder )
122+ }
123+ if (is_empty(gdf )) {
124+ print(" No geocoder, getting current bbox" )
125+ bbox <- input $ map_bbox
126+ print(bbox )
127+ if (! is.null(bbox )) {
128+ gdf <- get_polygon_bbox(bbox )
129+ }
130+ }
131+
132+ if (is_empty(gdf )) {
133+ warning(" No selection found, using default!" )
134+ return (spData :: us_states )
135+ }
136+
137+ gdf
138+ }
139+
117140 # Set up the map:
118141 output $ map <- renderMaplibre({
119142 m <- mapgl :: maplibre(
120- zoom = 1 ,
143+ zoom = 2 ,
121144 center = c(- 80 , 20 ),
122145 maxZoom = input $ max_zoom
123146 )
@@ -138,7 +161,7 @@ server <- function(input, output, session) {
138161 m | > add_countries()
139162 })
140163
141- # React to layer selection
164+ # Update map to show selected layer (polygons)
142165 observeEvent(input $ layer_selection , {
143166 proxy <- maplibre_proxy(" map" )
144167
@@ -160,7 +183,25 @@ server <- function(input, output, session) {
160183 proxy | > set_filter(input $ layer_selection , layer_filter())
161184 })
162185
163- # React to selected feature
186+ # Observe chat input
187+ observeEvent(input $ chat_user_input , {
188+ taxa_selected <- txt_to_taxa(input $ chat_user_input )
189+ chat_append(" chat" , " done" )
190+
191+ # optionally - store the selection as global variable for future reactions
192+ taxa_filter(taxa_selected )
193+
194+ # we can react right away, computing richness and updating map
195+ gdf <- get_richness(
196+ poly = get_active_feature(input ),
197+ zoom = as.integer(input $ map_zoom ),
198+ taxa_selections = taxa_selected
199+ )
200+ maplibre_proxy(" map" ) | >
201+ add_richness(gdf )
202+ })
203+
204+ # Zoom into selected feature, move down a layer, show resulting child features
164205 observeEvent(input $ map_feature_click , {
165206 # NOTE: This reacts to drawing features too
166207
@@ -185,14 +226,6 @@ server <- function(input, output, session) {
185226 return ()
186227 }
187228
188- # record info about currently selected feature
189- selected_feature(list (
190- name = name ,
191- layer = x $ layer ,
192- config = config ,
193- properties = x $ properties
194- ))
195-
196229 # Set the filter to focus on the clicked feature only
197230 layer_filter(list (
198231 " ==" ,
@@ -211,60 +244,31 @@ server <- function(input, output, session) {
211244 selected = config $ next_layer
212245 )
213246
214- # Optional logging to console
215- print(paste(
216- " Activating" ,
217- config $ next_layer ,
218- " and filtering" ,
219- config $ filter_column ,
220- " =" ,
221- selected
222- ))
247+ lazy_gdf <- activate_from_config(x $ properties $ id , config )
248+ active_feature(lazy_gdf ) # can a lazy feature be global var?
223249 }
224250 })
225251
226- observeEvent(input $ get_richness , {
227- # do nothing if no feature is selected? Alternately grab screen?
228- x <- selected_feature()
229- if (is.null(x )) {
230- warning(" select a feature first" )
231- return ()
232- }
233-
234- # selected_feature() must return these. make this more robust
235- id <- x $ properties $ id
236- zoom <- as.integer(input $ map_zoom )
237- poly <- open_dataset(x $ config $ parquet )
238-
239- # FIXME abstract this into selected_feature() behavior.
240- if (" id" %in% colnames(poly )) {
241- poly <- poly | >
242- filter(.data [[" id" ]] == !! id )
243- }
244- if (" geometry" %in% colnames(poly )) {
245- poly <- poly | > rename(geom = geometry )
246- }
247-
248- selected_taxa <- taxa_filter()
249-
250- print(selected_taxa )
252+ # logging helper
253+ print_selections <- function () {
251254 print(paste(
252255 " Computing biodiversity for" ,
253- x $ name ,
256+ digest :: digest(active_feature()) ,
254257 " at zoom" ,
255- zoom ,
258+ as.integer( input $ map_zoom ) ,
256259 " for taxa:" ,
257- paste(selected_taxa , collapse = " :" )
260+ paste(taxa_filter() , collapse = " :" )
258261 ))
262+ }
263+
264+ observeEvent(input $ get_richness , {
259265 gdf <- get_richness(
260- poly = poly ,
261- zoom = zoom ,
262- taxa_selections = selected_taxa
266+ poly = get_active_feature( input ) ,
267+ zoom = as.integer( input $ map_zoom ) ,
268+ taxa_selections = taxa_filter()
263269 )
264270
265- print(paste(nrow(gdf ), " features" ))
266271 maplibre_proxy(" map" ) | >
267- clear_layer(x $ config $ next_layer ) | >
268272 add_richness(gdf )
269273 })
270274
@@ -276,34 +280,24 @@ server <- function(input, output, session) {
276280 observeEvent(input $ get_features , {
277281 print(" Extracting drawn features" )
278282
279- drawn_features <- get_drawn_features(maplibre_proxy(" map" ))
280- print(drawn_features )
283+ gdf <- get_drawn_features(maplibre_proxy(" map" ))
284+ active_feature(gdf )
285+ print(gdf )
281286 })
282287
283288 observeEvent(input $ current_bbox , {
284289 gdf <- get_polygon_bbox(input $ map_bbox )
285- activate_polygon(gdf , name = " gdf" )
286- # Should we grab polygons from active layer inside bbox?
287- # Could allow for better cache behavior
290+ active_feature(gdf )
291+ # Should we grab polygons from active layer inside bbox instead to cache?
288292 })
289293
290294 # Ex: Get POINT data from geocoder (OSM)
291- # could then react by operating on hex or some containing polygon
292295 observeEvent(input $ map_geocoder $ result , {
293- temp <- tempfile(fileext = " .geojson" )
294- output <- list (
295- type = " FeatureCollection" ,
296- features = input $ map_geocoder $ result $ features
297- )
298- jsonlite :: write_json(
299- output ,
300- temp ,
301- auto_unbox = TRUE
302- )
303- geo <- sf :: st_read(temp )
296+ gdf <- geocoder_to_gdf(input $ map_geocoder )
297+ # active_feature(gdf)
304298
305- # get parent polygon from active layer via duckdbfs st_contains
306- print(geo )
299+ # Get value of various layers based on containing hex of given zoom
300+ print(gdf )
307301 })
308302
309303 observeEvent(input $ clear_richness , {
@@ -312,7 +306,13 @@ server <- function(input, output, session) {
312306
313307 # Manual taxonomic controls
314308 observeEvent(taxa_selections $ filter_trigger(), {
315- taxa_filter(taxa_selections $ selections())
309+ gdf <- get_richness(
310+ poly = get_active_feature(input ),
311+ zoom = as.integer(input $ map_zoom ),
312+ taxa_selections = taxa_selections $ selections()
313+ )
314+ maplibre_proxy(" map" ) | >
315+ add_richness(gdf )
316316 })
317317
318318 # Toggle draw controls
0 commit comments