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

138 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-10-23 12:35 +0000

1# https://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6import math 

7 

8from pyrocko.guts import Int, StringChoice, Bool, Float 

9from pyrocko.gui.qt_compat import qw, qc 

10 

11from .. import common 

12from pyrocko.gui.vtk_util import TrimeshPipe 

13from .base import Element, ElementState 

14from pyrocko import icosphere 

15from pyrocko.geometry import r2d 

16from pyrocko.color import Color 

17 

18km = 1000. 

19 

20guts_prefix = 'sparrow' 

21 

22 

23class IcosphereBaseChoice(StringChoice): 

24 choices = ['icosahedron', 'tetrahedron', 'tcube'] 

25 

26 

27class IcosphereKindChoice(StringChoice): 

28 choices = ['kind1', 'kind2'] 

29 

30 

31class IcosphereState(ElementState): 

32 base = IcosphereBaseChoice.T(default='icosahedron') 

33 kind = IcosphereKindChoice.T(default='kind1') 

34 level = Int.T(default=0) 

35 visible = Bool.T(default=True) 

36 smooth = Bool.T(default=False) 

37 color = Color.T(default=Color.D('aluminium5')) 

38 

39 ambient = Float.T(default=0.0) 

40 diffuse = Float.T(default=1.0) 

41 specular = Float.T(default=0.0) 

42 

43 opacity = Float.T(default=1.0) 

44 depth = Float.T(default=30.0*km) 

45 

46 def create(self): 

47 element = IcosphereElement() 

48 return element 

49 

50 

51class IcosphereElement(Element): 

52 

53 def __init__(self): 

54 Element.__init__(self) 

55 self._mesh = None 

56 self._controls = None 

57 self._params = None 

58 

59 def get_name(self): 

60 return 'Icosphere' 

61 

62 def bind_state(self, state): 

63 Element.bind_state(self, state) 

64 variables = [ 

65 'visible', 'level', 'base', 'kind', 'smooth', 'color', 'ambient', 

66 'diffuse', 'specular', 'depth', 'opacity'] 

67 

68 self.talkie_connect(state, variables, self.update) 

69 

70 def set_parent(self, parent): 

71 Element.set_parent(self, parent) 

72 self.talkie_connect(self._parent.state, 'dip', self.update) 

73 

74 self._parent.add_panel( 

75 self.get_title_label(), 

76 self._get_controls(), 

77 visible=True, 

78 title_controls=[ 

79 self.get_title_control_remove(), 

80 self.get_title_control_visible()]) 

81 

82 self.update() 

83 

84 def unset_parent(self): 

85 self.unbind_state() 

86 if self._parent: 

87 if self._mesh: 

88 self._parent.remove_actor(self._mesh.actor) 

89 self._mesh = None 

90 

91 if self._controls: 

92 self._parent.remove_panel(self._controls) 

93 self._controls = None 

94 

95 self._parent.update_view() 

96 self._parent = None 

97 

98 def update(self, *args): 

99 state = self._state 

100 

101 params = state.level, state.base, state.kind, state.smooth 

102 

103 if self._mesh and (params != self._params or not state.visible): 

104 self._parent.remove_actor(self._mesh.actor) 

105 self._mesh = None 

106 

107 if state.visible and not self._mesh: 

108 vertices, faces = icosphere.sphere( 

109 state.level, state.base, state.kind, radius=1.0, 

110 triangulate=False) 

111 

112 self._vertices = vertices 

113 self._depth = 0.0 

114 

115 self._mesh = TrimeshPipe(vertices, faces, smooth=state.smooth) 

116 self._params = params 

117 

118 self._parent.add_actor(self._mesh.actor) 

119 

120 if self._parent.state.distance < 2.0: 

121 angle = 180. - math.acos(self._parent.state.distance / 2.0)*r2d 

122 

123 opacity = min( 

124 1.0, 

125 max(0., (angle+5. - self._parent.state.dip) / 10.)) 

126 else: 

127 opacity = 1.0 

128 

129 opacity *= state.opacity 

130 

131 if self._mesh: 

132 if self._depth != state.depth: 

133 radius = (self._parent.planet_radius - state.depth) \ 

134 / self._parent.planet_radius 

135 

136 self._mesh.set_vertices(self._vertices * radius) 

137 self._depth = state.depth 

138 

139 self._mesh.set_opacity(opacity) 

140 self._mesh.set_color(state.color) 

141 self._mesh.set_ambient(state.ambient) 

142 self._mesh.set_diffuse(state.diffuse) 

143 self._mesh.set_specular(state.specular) 

144 

145 self._parent.update_view() 

146 

147 def _get_controls(self): 

148 state = self._state 

149 if not self._controls: 

150 from ..state import state_bind_slider, \ 

151 state_bind_combobox, state_bind_checkbox, \ 

152 state_bind_combobox_color, state_bind_lineedit 

153 

154 frame = qw.QFrame() 

155 layout = qw.QGridLayout() 

156 frame.setLayout(layout) 

157 

158 slider = qw.QSlider(qc.Qt.Horizontal) 

159 slider.setSizePolicy( 

160 qw.QSizePolicy( 

161 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed)) 

162 slider.setMinimum(0) 

163 slider.setMaximum(5) 

164 slider.setSingleStep(1) 

165 slider.setPageStep(1) 

166 

167 layout.addWidget(qw.QLabel('Level'), 0, 0) 

168 layout.addWidget(slider, 0, 1) 

169 

170 state_bind_slider(self, state, 'level', slider, dtype=int) 

171 

172 cb = common.string_choices_to_combobox(IcosphereBaseChoice) 

173 layout.addWidget(qw.QLabel('Base'), 1, 0) 

174 layout.addWidget(cb, 1, 1) 

175 state_bind_combobox(self, state, 'base', cb) 

176 

177 cb = common.string_choices_to_combobox(IcosphereKindChoice) 

178 layout.addWidget(qw.QLabel('Kind'), 2, 0) 

179 layout.addWidget(cb, 2, 1) 

180 state_bind_combobox(self, state, 'kind', cb) 

181 

182 layout.addWidget(qw.QLabel('Color'), 3, 0) 

183 

184 cb = common.strings_to_combobox( 

185 ['black', 'aluminium6', 'aluminium5', 'aluminium4', 

186 'aluminium3', 'aluminium2', 'aluminium1', 'white', 

187 'scarletred2', 'orange2', 'skyblue2', 'plum2']) 

188 

189 layout.addWidget(cb, 3, 1) 

190 state_bind_combobox_color( 

191 self, self._state, 'color', cb) 

192 

193 def add_slider(title, param, irow): 

194 layout.addWidget(qw.QLabel(title), irow, 0) 

195 

196 slider = qw.QSlider(qc.Qt.Horizontal) 

197 slider.setSizePolicy( 

198 qw.QSizePolicy( 

199 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed)) 

200 slider.setMinimum(0) 

201 slider.setMaximum(1000) 

202 layout.addWidget(slider, irow, 1) 

203 

204 state_bind_slider( 

205 self, state, param, slider, factor=0.001) 

206 

207 add_slider('Opacity', 'opacity', 4) 

208 add_slider('Ambient', 'ambient', 5) 

209 add_slider('Diffuse', 'diffuse', 6) 

210 add_slider('Specular', 'specular', 7) 

211 

212 cb = qw.QCheckBox('Smooth') 

213 layout.addWidget(cb, 8, 1) 

214 state_bind_checkbox(self, state, 'smooth', cb) 

215 

216 layout.addWidget(qw.QLabel('Depth [km]'), 9, 0) 

217 le = qw.QLineEdit() 

218 layout.addWidget(le, 9, 1) 

219 state_bind_lineedit( 

220 self, state, 'depth', le, 

221 from_string=lambda s: float(s)*1000., 

222 to_string=lambda v: str(v/1000.)) 

223 

224 layout.addWidget(qw.QFrame(), 10, 0, 1, 2) 

225 

226 self._controls = frame 

227 

228 return self._controls 

229 

230 

231__all__ = [ 

232 'IcosphereElement', 

233 'IcosphereState', 

234 'IcosphereKindChoice', 

235 'IcosphereBaseChoice']