Coverage for gws-app/gws/plugin/raster_layer/layer.py: 93%

54 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-16 22:59 +0200

1"""Raster image layer.""" 

2 

3from typing import Optional 

4 

5import gws 

6import gws.base.layer 

7import gws.base.shape 

8import gws.config.util 

9import gws.gis.gdalx 

10import gws.gis.ms 

11import gws.gis.ms.util 

12import gws.gis.zoom 

13import gws.lib.bounds 

14import gws.lib.crs 

15import gws.lib.osx 

16 

17from . import provider 

18 

19gws.ext.new.layer('raster') 

20 

21 

22class Config(gws.base.layer.Config): 

23 """Raster layer""" 

24 

25 provider: provider.Config 

26 """Raster provider""" 

27 processing: Optional[list[str]] 

28 """Processing directives.""" 

29 transparentColor: Optional[str] 

30 """Color to treat as transparent in the layer.""" 

31 sldPath: Optional[gws.FilePath] 

32 """Path to SLD file for styling the layer.""" 

33 sldName: Optional[str] 

34 """Name of an SLD NamedLayer to apply.""" 

35 

36 

37class Object(gws.base.layer.image.Object): 

38 serviceProvider: provider.Object 

39 entries: list[provider.ImageEntry] 

40 msOptions: gws.gis.ms.LayerOptions 

41 

42 def configure(self): 

43 self.msOptions = gws.gis.ms.LayerOptions( 

44 type=gws.gis.ms.LayerType.raster, 

45 processing=self.cfg('processing', default=[]), 

46 transparentColor=self.cfg('transparentColor'), 

47 sldPath=self.cfg('sldPath'), 

48 sldName=self.cfg('sldName'), 

49 ) 

50 self.configure_layer() 

51 

52 def configure_provider(self): 

53 gws.config.util.configure_service_provider_for(self, provider.Object) 

54 

55 default_crs = self.serviceProvider.crs or self.parentBounds.crs 

56 self.entries = self.serviceProvider.enumerate_images(default_crs) 

57 if not self.entries: 

58 raise gws.ConfigurationError('no images found') 

59 

60 self.msOptions.crs = self.entries[0].bounds.crs 

61 self.msOptions.tileIndex = self.serviceProvider.make_tile_index( 

62 self.entries, 

63 file_name=f'raster_layer_{self.uid}', 

64 ) 

65 # self.msOptions.path = self.entries[0].path 

66 

67 def configure_bounds(self): 

68 if super().configure_bounds(): 

69 return True 

70 b = gws.lib.bounds.union([e.bounds for e in self.entries]) 

71 self.bounds = gws.lib.bounds.transform(b, self.parentBounds.crs) 

72 return True 

73 

74 def configure_grid(self): 

75 p = self.cfg('grid') or gws.base.layer.GridConfig() 

76 

77 self.grid = gws.TileGrid( 

78 origin=p.origin or gws.Origin.nw, 

79 tileSize=p.tileSize or 256, 

80 bounds=self.bounds, 

81 ) 

82 

83 if p.resolutions: 

84 self.grid.resolutions = p.resolutions 

85 else: 

86 self.grid.resolutions = gws.gis.zoom.resolutions_from_bounds(self.grid.bounds, self.grid.tileSize) 

87 

88 def render(self, lri): 

89 return gws.gis.ms.util.raster_render(self, lri)