fffiloni commited on
Commit
58802ff
·
verified ·
1 Parent(s): 1eaacd9

Tune gradient fade thickness by format and orientation

Browse files
Files changed (1) hide show
  1. create_map_poster.py +65 -22
create_map_poster.py CHANGED
@@ -165,13 +165,15 @@ def crop_axes_to_ratio(ax, target_ratio, pad=0.03):
165
  ax.set_ylim(cy - new_h / 2, cy + new_h / 2)
166
 
167
 
168
- def create_gradient_fade(ax, color, location='bottom', zorder=10):
169
  """
170
- Creates a fade effect at the top or bottom of the map
171
- without altering the map aspect/limits.
 
172
  """
 
 
173
  vals = np.linspace(0, 1, 256).reshape(-1, 1)
174
- gradient = np.hstack((vals, vals))
175
 
176
  rgb = mcolors.to_rgb(color)
177
  my_colors = np.zeros((256, 4))
@@ -179,29 +181,50 @@ def create_gradient_fade(ax, color, location='bottom', zorder=10):
179
  my_colors[:, 1] = rgb[1]
180
  my_colors[:, 2] = rgb[2]
181
 
182
- if location == 'bottom':
183
- my_colors[:, 3] = np.linspace(1, 0, 256)
184
- extent_y_start = 0
185
- extent_y_end = 0.25
186
- else:
187
- my_colors[:, 3] = np.linspace(0, 1, 256)
188
- extent_y_start = 0.75
189
- extent_y_end = 1.0
190
-
191
- custom_cmap = mcolors.ListedColormap(my_colors)
192
-
193
  # Save current view/aspect so imshow can't distort the map
194
  xlim = ax.get_xlim()
195
  ylim = ax.get_ylim()
196
  aspect = ax.get_aspect()
197
 
 
198
  y_range = ylim[1] - ylim[0]
199
- y_bottom = ylim[0] + y_range * extent_y_start
200
- y_top = ylim[0] + y_range * extent_y_end
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
  ax.imshow(
203
  gradient,
204
- extent=[xlim[0], xlim[1], y_bottom, y_top],
205
  aspect='auto',
206
  cmap=custom_cmap,
207
  zorder=zorder,
@@ -420,6 +443,22 @@ def create_poster(city, country, point, dist, output_file):
420
  orientation = THEME.get("_orientation", "portrait")
421
  figsize = get_figsize(map_format, orientation)
422
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  fig = plt.figure(figsize=figsize, facecolor=THEME['bg'])
424
 
425
  # Map axis: full-bleed
@@ -451,12 +490,16 @@ def create_poster(city, country, point, dist, output_file):
451
  )
452
 
453
  # Crop view to match output aspect ratio
454
- target_ratio = figsize[0] / figsize[1]
455
  crop_axes_to_ratio(ax_map, target_ratio=target_ratio, pad=MAP_PAD)
456
 
457
- # Layer 3: gradients
458
- create_gradient_fade(ax_map, THEME['gradient_color'], location='bottom', zorder=10)
459
- create_gradient_fade(ax_map, THEME['gradient_color'], location='top', zorder=10)
 
 
 
 
 
460
 
461
  # Build displayed strings
462
  spaced_city = " ".join(list(city.upper()))
 
165
  ax.set_ylim(cy - new_h / 2, cy + new_h / 2)
166
 
167
 
168
+ def create_gradient_fade(ax, color, location='bottom', zorder=10, thickness=0.25):
169
  """
170
+ Creates a fade effect at the edges of the map without altering aspect/limits.
171
+ location: 'bottom', 'top', 'left', 'right'
172
+ thickness: fraction of the axis range to cover (e.g. 0.25 = 25%)
173
  """
174
+ thickness = float(max(0.02, min(0.40, thickness))) # clamp safe
175
+
176
  vals = np.linspace(0, 1, 256).reshape(-1, 1)
 
177
 
178
  rgb = mcolors.to_rgb(color)
179
  my_colors = np.zeros((256, 4))
 
181
  my_colors[:, 1] = rgb[1]
182
  my_colors[:, 2] = rgb[2]
183
 
 
 
 
 
 
 
 
 
 
 
 
184
  # Save current view/aspect so imshow can't distort the map
185
  xlim = ax.get_xlim()
186
  ylim = ax.get_ylim()
187
  aspect = ax.get_aspect()
188
 
189
+ x_range = xlim[1] - xlim[0]
190
  y_range = ylim[1] - ylim[0]
191
+
192
+ if location == 'bottom':
193
+ gradient = np.hstack((vals, vals)) # vertical
194
+ my_colors[:, 3] = np.linspace(1, 0, 256)
195
+ y0 = ylim[0]
196
+ y1 = ylim[0] + y_range * thickness
197
+ extent = [xlim[0], xlim[1], y0, y1]
198
+
199
+ elif location == 'top':
200
+ gradient = np.hstack((vals, vals)) # vertical
201
+ my_colors[:, 3] = np.linspace(0, 1, 256)
202
+ y0 = ylim[1] - y_range * thickness
203
+ y1 = ylim[1]
204
+ extent = [xlim[0], xlim[1], y0, y1]
205
+
206
+ elif location == 'left':
207
+ gradient = np.vstack((vals.T, vals.T)) # horizontal
208
+ my_colors[:, 3] = np.linspace(1, 0, 256)
209
+ x0 = xlim[0]
210
+ x1 = xlim[0] + x_range * thickness
211
+ extent = [x0, x1, ylim[0], ylim[1]]
212
+
213
+ elif location == 'right':
214
+ gradient = np.vstack((vals.T, vals.T)) # horizontal
215
+ my_colors[:, 3] = np.linspace(0, 1, 256)
216
+ x0 = xlim[1] - x_range * thickness
217
+ x1 = xlim[1]
218
+ extent = [x0, x1, ylim[0], ylim[1]]
219
+
220
+ else:
221
+ return
222
+
223
+ custom_cmap = mcolors.ListedColormap(my_colors)
224
 
225
  ax.imshow(
226
  gradient,
227
+ extent=extent,
228
  aspect='auto',
229
  cmap=custom_cmap,
230
  zorder=zorder,
 
443
  orientation = THEME.get("_orientation", "portrait")
444
  figsize = get_figsize(map_format, orientation)
445
 
446
+ target_ratio = figsize[0] / figsize[1] # width/height
447
+
448
+ # Tune fade thickness by format/orientation (carto-friendly defaults)
449
+ if map_format == "panoramic" and orientation == "landscape":
450
+ fade_tb = 0.12
451
+ fade_lr = 0.22
452
+ elif orientation == "landscape":
453
+ fade_tb = 0.15
454
+ fade_lr = 0.18
455
+ elif map_format == "plan":
456
+ fade_tb = 0.18
457
+ fade_lr = 0.18
458
+ else: # portrait (default)
459
+ fade_tb = 0.22
460
+ fade_lr = 0.10
461
+
462
  fig = plt.figure(figsize=figsize, facecolor=THEME['bg'])
463
 
464
  # Map axis: full-bleed
 
490
  )
491
 
492
  # Crop view to match output aspect ratio
 
493
  crop_axes_to_ratio(ax_map, target_ratio=target_ratio, pad=MAP_PAD)
494
 
495
+ # Layer 3: gradients (thickness adapts to layout)
496
+ create_gradient_fade(ax_map, THEME['gradient_color'], location='bottom', zorder=10, thickness=fade_tb)
497
+ create_gradient_fade(ax_map, THEME['gradient_color'], location='top', zorder=10, thickness=fade_tb)
498
+
499
+ # Add side fades for wide layouts; thinner in portrait by design
500
+ if target_ratio >= 1.15:
501
+ create_gradient_fade(ax_map, THEME['gradient_color'], location='left', zorder=10, thickness=fade_lr)
502
+ create_gradient_fade(ax_map, THEME['gradient_color'], location='right', zorder=10, thickness=fade_lr)
503
 
504
  # Build displayed strings
505
  spaced_city = " ".join(list(city.upper()))