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

1from typing import Optional 

2 

3import gws 

4import gws.gis.extent 

5import gws.lib.uom as units 

6 

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)""" 

31 

32OSM_RESOLUTIONS = list(reversed([units.scale_to_res(s) for s in OSM_SCALES])) 

33"""Resolutions corresponding to OSM zoom levels.""" 

34 

35 

36class Config(gws.Config): 

37 """Zoom levels and resolutions""" 

38 

39 resolutions: Optional[list[float]] 

40 """allowed resolutions""" 

41 initResolution: Optional[float] 

42 """initial resolution""" 

43 

44 scales: Optional[list[float]] 

45 """allowed scales""" 

46 initScale: Optional[float] 

47 """initial scale""" 

48 

49 minResolution: Optional[float] 

50 """minimal resolution""" 

51 maxResolution: Optional[float] 

52 """maximal resolution""" 

53 

54 minScale: Optional[float] 

55 """minimal scale""" 

56 maxScale: Optional[float] 

57 """maximal scale""" 

58 

59 

60def resolutions_from_config(cfg, parent_resolutions: list[float] = None) -> list[float]: 

61 """Loads resolution from a config. 

62 

63 Args: 

64 cfg: A config. 

65 parent_resolutions: List of parent resolutions. 

66 

67 Returns: 

68 A list of resolutions. 

69 """ 

70 

71 # see also https://mapproxy.org/docs/1.11.0/configuration.html#res and below 

72 

73 # @TODO deal with scales separately 

74 

75 rmin = _res_or_scale(cfg, 'minResolution', 'minScale') 

76 rmax = _res_or_scale(cfg, 'maxResolution', 'maxScale') 

77 

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) 

85 

86 return sorted(set(res)) 

87 

88 

89def resolutions_from_source_layers(source_layers: list[gws.SourceLayer], parent_resolutions: list[float]) -> list[ 

90 float]: 

91 """Loads resolution from a source layers. 

92 

93 Args: 

94 source_layers: Source layers. 

95 parent_resolutions: List of parent resolutions. 

96 

97 Returns: 

98 A list of resolutions. 

99 """ 

100 

101 smin = [] 

102 smax = [] 

103 

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]) 

110 

111 if not smin: 

112 return parent_resolutions 

113 

114 rmin = units.scale_to_res(min(smin)) 

115 rmax = units.scale_to_res(max(smax)) 

116 

117 pmin = min(parent_resolutions) 

118 pmax = max(parent_resolutions) 

119 

120 if rmin > pmax or rmax < pmin: 

121 return [] 

122 

123 lt = [r for r in parent_resolutions if r <= rmin] 

124 gt = [r for r in parent_resolutions if r >= rmax] 

125 

126 rmin = max(lt) if lt else pmin 

127 rmax = min(gt) if gt else pmax 

128 

129 return [r for r in parent_resolutions if rmin <= r <= rmax] 

130 

131 

132def resolutions_from_bounds(b: gws.Bounds, tile_size: int) -> list[float]: 

133 """Loads resolutions from bounds. 

134 

135 Args: 

136 b: Bounds object. 

137 tile_size: The tile size. 

138 

139 Returns: 

140 A list of resolutions. 

141 """ 

142 

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 

148 

149 

150def init_resolution(cfg, resolutions: list) -> float: 

151 """Returns the initial resolution. 

152 

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)) 

161 

162 

163def _explicit_resolutions(cfg): 

164 ls = gws.u.get(cfg, 'resolutions') 

165 if ls: 

166 return ls 

167 

168 ls = gws.u.get(cfg, 'scales') 

169 if ls: 

170 return [units.scale_to_res(x) for x in ls] 

171 

172 

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)