mbuuck commited on
Commit
53423c0
·
1 Parent(s): ea36e3b

Added an autozoom feature

Browse files
Files changed (1) hide show
  1. app.py +49 -5
app.py CHANGED
@@ -242,6 +242,49 @@ def create_dataframe(years, project_name):
242
  dfs.append(df)
243
  return pd.concat(dfs)
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  def show_project_map(project_name):
246
  prepared_statement = \
247
  con.execute("SELECT geometry FROM project WHERE name = ? LIMIT 1",
@@ -249,18 +292,19 @@ def show_project_map(project_name):
249
  features = \
250
  json.loads(prepared_statement[0][0].replace("\'", "\""))['features']
251
  geometry = features[0]['geometry']
252
- x_centroid = np.mean(np.array(geometry["coordinates"])[0, :, 0])
253
- y_centroid = np.mean(np.array(geometry["coordinates"])[0, :, 1])
 
254
  fig = go.Figure(go.Scattermapbox(
255
  mode = "markers",
256
- lon = [x_centroid], lat = [y_centroid],
257
  marker = {'size': 20, 'color': ["cyan"]}))
258
 
259
  fig.update_layout(
260
  mapbox = {
261
  'style': "stamen-terrain",
262
- 'center': { 'lon': x_centroid, 'lat': y_centroid},
263
- 'zoom': 12, 'layers': [{
264
  'source': {
265
  'type': "FeatureCollection",
266
  'features': [{
 
242
  dfs.append(df)
243
  return pd.concat(dfs)
244
 
245
+ # h/t: https://community.plotly.com/t/dynamic-zoom-for-mapbox/32658/12
246
+ def get_plotting_zoom_level_and_center_coordinates_from_lonlat_tuples(longitudes=None, latitudes=None):
247
+ """Function documentation:\n
248
+ Basic framework adopted from Krichardson under the following thread:
249
+ https://community.plotly.com/t/dynamic-zoom-for-mapbox/32658/7
250
+
251
+ # NOTE:
252
+ # THIS IS A TEMPORARY SOLUTION UNTIL THE DASH TEAM IMPLEMENTS DYNAMIC ZOOM
253
+ # in their plotly-functions associated with mapbox, such as go.Densitymapbox() etc.
254
+
255
+ Returns the appropriate zoom-level for these plotly-mapbox-graphics along with
256
+ the center coordinate tuple of all provided coordinate tuples.
257
+ """
258
+
259
+ # Check whether both latitudes and longitudes have been passed,
260
+ # or if the list lenghts don't match
261
+ if ((latitudes is None or longitudes is None)
262
+ or (len(latitudes) != len(longitudes))):
263
+ # Otherwise, return the default values of 0 zoom and the coordinate origin as center point
264
+ return 0, (0, 0)
265
+
266
+ # Get the boundary-box
267
+ b_box = {}
268
+ b_box['height'] = latitudes.max()-latitudes.min()
269
+ b_box['width'] = longitudes.max()-longitudes.min()
270
+ b_box['center']= (np.mean(longitudes), np.mean(latitudes))
271
+
272
+ # get the area of the bounding box in order to calculate a zoom-level
273
+ area = b_box['height'] * b_box['width']
274
+
275
+ # * 1D-linear interpolation with numpy:
276
+ # - Pass the area as the only x-value and not as a list, in order to return a scalar as well
277
+ # - The x-points "xp" should be in parts in comparable order of magnitude of the given area
278
+ # - The zpom-levels are adapted to the areas, i.e. start with the smallest area possible of 0
279
+ # which leads to the highest possible zoom value 20, and so forth decreasing with increasing areas
280
+ # as these variables are antiproportional
281
+ zoom = np.interp(x=area,
282
+ xp=[0, 5**-10, 4**-10, 3**-10, 2**-10, 1**-10, 1**-5],
283
+ fp=[20, 15, 14, 13, 12, 7, 5])
284
+
285
+ # Finally, return the zoom level and the associated boundary-box center coordinates
286
+ return zoom, b_box['center']
287
+
288
  def show_project_map(project_name):
289
  prepared_statement = \
290
  con.execute("SELECT geometry FROM project WHERE name = ? LIMIT 1",
 
292
  features = \
293
  json.loads(prepared_statement[0][0].replace("\'", "\""))['features']
294
  geometry = features[0]['geometry']
295
+ longitudes = np.array(geometry["coordinates"])[0, :, 0]
296
+ latitudes = np.array(geometry["coordinates"])[0, :, 1]
297
+ zoom, bbox_center = get_plotting_zoom_level_and_center_coordinates_from_lonlat_tuples(longitudes, latitudes)
298
  fig = go.Figure(go.Scattermapbox(
299
  mode = "markers",
300
+ lon = [bbox_center[0]], lat = [bbox_center[1]],
301
  marker = {'size': 20, 'color': ["cyan"]}))
302
 
303
  fig.update_layout(
304
  mapbox = {
305
  'style': "stamen-terrain",
306
+ 'center': { 'lon': bbox_center[0], 'lat': bbox_center[1]},
307
+ 'zoom': zoom, 'layers': [{
308
  'source': {
309
  'type': "FeatureCollection",
310
  'features': [{