Spaces:
Build error
Build error
Added an autozoom feature
Browse files
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 |
-
|
253 |
-
|
|
|
254 |
fig = go.Figure(go.Scattermapbox(
|
255 |
mode = "markers",
|
256 |
-
lon = [
|
257 |
marker = {'size': 20, 'color': ["cyan"]}))
|
258 |
|
259 |
fig.update_layout(
|
260 |
mapbox = {
|
261 |
'style': "stamen-terrain",
|
262 |
-
'center': { 'lon':
|
263 |
-
'zoom':
|
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': [{
|