Coverage for gws-app/gws/gis/zoom/__init__.py: 0%
83 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
1from typing import Optional
3import gws
4import gws.gis.extent
5import gws.lib.uom as units
7OSM_SCALES = [
8 500_000_000,
9 250_000_000,
10 150_000_000,
11 70_000_000,
12 35_000_000,
13 15_000_000,
14 10_000_000,
15 4_000_000,
16 2_000_000,
17 1_000_000,
18 500_000,
19 250_000,
20 150_000,
21 70_000,
22 35_000,
23 15_000,
24 8_000,
25 4_000,
26 2_000,
27 1_000,
28 500,
29]
30"""Scales corresponding to OSM zoom levels. (https://wiki.openstreetmap.org/wiki/Zoom_levels)"""
32OSM_RESOLUTIONS = list(reversed([units.scale_to_res(s) for s in OSM_SCALES]))
33"""Resolutions corresponding to OSM zoom levels."""
36class Config(gws.Config):
37 """Zoom levels and resolutions"""
39 resolutions: Optional[list[float]]
40 """allowed resolutions"""
41 initResolution: Optional[float]
42 """initial resolution"""
44 scales: Optional[list[float]]
45 """allowed scales"""
46 initScale: Optional[float]
47 """initial scale"""
49 minResolution: Optional[float]
50 """minimal resolution"""
51 maxResolution: Optional[float]
52 """maximal resolution"""
54 minScale: Optional[float]
55 """minimal scale"""
56 maxScale: Optional[float]
57 """maximal scale"""
60def resolutions_from_config(cfg, parent_resolutions: list[float] = None) -> list[float]:
61 """Loads resolution from a config.
63 Args:
64 cfg: A config.
65 parent_resolutions: List of parent resolutions.
67 Returns:
68 A list of resolutions.
69 """
71 # see also https://mapproxy.org/docs/1.11.0/configuration.html#res and below
73 # @TODO deal with scales separately
75 rmin = _res_or_scale(cfg, 'minResolution', 'minScale')
76 rmax = _res_or_scale(cfg, 'maxResolution', 'maxScale')
78 res = _explicit_resolutions(cfg) or parent_resolutions or list(OSM_RESOLUTIONS)
79 if rmax and rmax < max(res):
80 res = [r for r in res if r < rmax]
81 res.append(rmax)
82 if rmin and rmin > min(res):
83 res = [r for r in res if r > rmin]
84 res.append(rmin)
86 return sorted(set(res))
89def resolutions_from_source_layers(source_layers: list[gws.SourceLayer], parent_resolutions: list[float]) -> list[
90 float]:
91 """Loads resolution from a source layers.
93 Args:
94 source_layers: Source layers.
95 parent_resolutions: List of parent resolutions.
97 Returns:
98 A list of resolutions.
99 """
101 smin = []
102 smax = []
104 for sl in source_layers:
105 sr = sl.scaleRange
106 if not sr:
107 return parent_resolutions
108 smin.append(sr[0])
109 smax.append(sr[1])
111 if not smin:
112 return parent_resolutions
114 rmin = units.scale_to_res(min(smin))
115 rmax = units.scale_to_res(max(smax))
117 pmin = min(parent_resolutions)
118 pmax = max(parent_resolutions)
120 if rmin > pmax or rmax < pmin:
121 return []
123 lt = [r for r in parent_resolutions if r <= rmin]
124 gt = [r for r in parent_resolutions if r >= rmax]
126 rmin = max(lt) if lt else pmin
127 rmax = min(gt) if gt else pmax
129 return [r for r in parent_resolutions if rmin <= r <= rmax]
132def resolutions_from_bounds(b: gws.Bounds, tile_size: int) -> list[float]:
133 """Loads resolutions from bounds.
135 Args:
136 b: Bounds object.
137 tile_size: The tile size.
139 Returns:
140 A list of resolutions.
141 """
143 siz = gws.gis.extent.size(b.extent)
144 res = []
145 for z in range(20):
146 res.append(siz[0] / (tile_size * (1 << z)))
147 return res
150def init_resolution(cfg, resolutions: list) -> float:
151 """Returns the initial resolution.
153 Args:
154 cfg: A config.
155 resolutions: List of Resolutions.
156 """
157 init = _res_or_scale(cfg, 'initResolution', 'initScale')
158 if not init:
159 return resolutions[len(resolutions) >> 1]
160 return min(resolutions, key=lambda r: abs(init - r))
163def _explicit_resolutions(cfg):
164 ls = gws.u.get(cfg, 'resolutions')
165 if ls:
166 return ls
168 ls = gws.u.get(cfg, 'scales')
169 if ls:
170 return [units.scale_to_res(x) for x in ls]
173def _res_or_scale(cfg, r, s):
174 x = gws.u.get(cfg, r)
175 if x:
176 return x
177 x = gws.u.get(cfg, s)
178 if x:
179 return units.scale_to_res(x)