Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/gui/sparrow/elements/crosshair.py: 46%

136 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-10-04 09:52 +0000

1import vtk 

2import numpy as num 

3 

4from pyrocko.gui.qt_compat import qw 

5from pyrocko import orthodrome as od 

6from pyrocko.gui import vtk_util 

7from pyrocko.guts import Bool 

8from pyrocko.color import Color 

9from .. import common 

10 

11from .base import Element, ElementState 

12 

13guts_prefix = 'sparrow' 

14 

15 

16def cross3d_flat(a=1., b=0.5): 

17 lines_ned = [] 

18 for i in range(2): 

19 for s in (-1., 1.): 

20 line = num.zeros((2, 3)) 

21 line[0, i] = s*a 

22 line[1, i] = s*b 

23 lines_ned.append(line) 

24 

25 return lines_ned 

26 

27 

28def cross3d(a=1., b=0.5): 

29 lines_ned = [] 

30 for i in range(3): 

31 for s in (-1., 1.): 

32 line = num.zeros((2, 3)) 

33 line[0, i] = s*a 

34 line[1, i] = s*b 

35 lines_ned.append(line) 

36 

37 return lines_ned 

38 

39 

40class Crosshair(object): 

41 def __init__(self): 

42 

43 self.mapper_surface = vtk.vtkDataSetMapper() 

44 self.mapper_position = vtk.vtkDataSetMapper() 

45 

46 self.actor_surface = vtk.vtkActor() 

47 self.actor_surface.SetMapper(self.mapper_surface) 

48 

49 self.actor_position = vtk.vtkActor() 

50 self.actor_position.SetMapper(self.mapper_position) 

51 

52 self._color = None 

53 self.set_color(Color('white')) 

54 

55 def get_actors(self): 

56 return [self.actor_surface, self.actor_position] 

57 

58 def make_multi_polyline(self, lat, lon, depth, size): 

59 lines_ned = cross3d_flat() 

60 lines_lld = [] 

61 for line_ned in lines_ned: 

62 line_ned_sized = size * line_ned 

63 line_lld = num.zeros(line_ned.shape) 

64 line_lld[:, :2] = num.vstack( 

65 od.ne_to_latlon( 

66 lat, lon, line_ned_sized[:, 0], line_ned_sized[:, 1])).T 

67 

68 line_lld[:, 2] = line_ned_sized[:, 2] 

69 lines_lld.append(line_lld) 

70 

71 mpl_surface = vtk_util.make_multi_polyline( 

72 lines_latlondepth=lines_lld) 

73 

74 lines_ned = cross3d() 

75 lines_lld = [] 

76 for line_ned in lines_ned: 

77 line_ned_sized = size * line_ned 

78 line_lld = num.zeros(line_ned.shape) 

79 line_lld[:, :2] = num.vstack( 

80 od.ne_to_latlon( 

81 lat, lon, line_ned_sized[:, 0], line_ned_sized[:, 1])).T 

82 

83 line_lld[:, 2] = depth + line_ned_sized[:, 2] 

84 lines_lld.append(line_lld) 

85 

86 mpl_position = vtk_util.make_multi_polyline( 

87 lines_latlondepth=lines_lld) 

88 

89 return [mpl_surface, mpl_position] 

90 

91 def set_geometry(self, lat, lon, depth, size): 

92 mpl_surface, mpl_position = self.make_multi_polyline( 

93 lat, lon, depth, size) 

94 vtk_util.vtk_set_input(self.mapper_surface, mpl_surface) 

95 vtk_util.vtk_set_input(self.mapper_position, mpl_position) 

96 self.actor_surface.GetProperty().SetOpacity( 

97 min(1.0, abs(depth) / size) * 0.5) 

98 

99 def set_color(self, color): 

100 if self._color is None or self._color != color: 

101 for actor in self.get_actors(): 

102 prop = actor.GetProperty() 

103 prop.SetDiffuseColor(color.rgb) 

104 

105 self._color = color 

106 

107 

108class CrosshairState(ElementState): 

109 visible = Bool.T(default=False) 

110 color = Color.T(default=Color.D('white')) 

111 

112 def __init__(self, *args, **kwargs): 

113 ElementState.__init__(self, *args, **kwargs) 

114 self.is_connected = False 

115 

116 def create(self): 

117 element = CrosshairElement() 

118 return element 

119 

120 

121class CrosshairElement(Element): 

122 

123 def __init__(self): 

124 Element.__init__(self) 

125 self._controls = None 

126 self._crosshair = None 

127 

128 def get_name(self): 

129 return 'Crosshair' 

130 

131 def bind_state(self, state): 

132 Element.bind_state(self, state) 

133 self.talkie_connect(state, ['visible', 'color'], self.update) 

134 

135 def set_parent(self, parent): 

136 Element.set_parent(self, parent) 

137 

138 self._parent.add_panel( 

139 self.get_title_label(), 

140 self._get_controls(), 

141 visible=False, 

142 title_controls=[ 

143 self.get_title_control_visible()]) 

144 

145 self.talkie_connect( 

146 self._parent.state, ['distance', 'lat', 'lon'], self.update) 

147 

148 self.update() 

149 

150 def unset_parent(self): 

151 self.unbind_state() 

152 if self._parent: 

153 if self._crosshair: 

154 self._parent.remove_actor(self._crosshair.actor) 

155 self._crosshair = None 

156 

157 if self._controls: 

158 self._parent.remove_panel(self._controls) 

159 self._controls = None 

160 

161 self._parent.update_view() 

162 self._parent = None 

163 

164 def update(self, *args): 

165 state = self._state 

166 pstate = self._parent.state 

167 

168 if state.visible: 

169 if not self._crosshair: 

170 self._crosshair = Crosshair() 

171 for actor in self._crosshair.get_actors(): 

172 self._parent.add_actor(actor) 

173 

174 size = pstate.distance * 100.*1000. 

175 self._crosshair.set_geometry( 

176 pstate.lat, pstate.lon, pstate.depth, size) 

177 self._crosshair.set_color(state.color) 

178 

179 else: 

180 if self._crosshair: 

181 for actor in self._crosshair.get_actors(): 

182 self._parent.remove_actor(actor) 

183 

184 self._crosshair = None 

185 

186 self._parent.update_view() 

187 

188 def _get_controls(self): 

189 if not self._controls: 

190 from ..state import state_bind_combobox_color 

191 

192 frame = qw.QFrame() 

193 layout = qw.QGridLayout() 

194 frame.setLayout(layout) 

195 

196 # color 

197 

198 layout.addWidget(qw.QLabel('Color'), 0, 0) 

199 

200 cb = common.strings_to_combobox( 

201 ['black', 'white', 'scarletred2']) 

202 

203 layout.addWidget(cb, 0, 1) 

204 state_bind_combobox_color(self, self._state, 'color', cb) 

205 

206 layout.addWidget(qw.QFrame(), 2, 0, 1, 2) 

207 

208 self._controls = frame 

209 

210 return self._controls 

211 

212 

213__all__ = [ 

214 'CrosshairElement', 

215 'CrosshairState']