1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6from __future__ import absolute_import, print_function, division
8import math
10from pyrocko.guts import Int, StringChoice, Bool, Float
11from pyrocko.gui.qt_compat import qw, qc
13from .. import common
14from pyrocko.gui.vtk_util import TrimeshPipe
15from .base import Element, ElementState
16from pyrocko import icosphere
17from pyrocko.geometry import r2d
18from pyrocko.color import Color
20km = 1000.
22guts_prefix = 'sparrow'
25class IcosphereBaseChoice(StringChoice):
26 choices = ['icosahedron', 'tetrahedron', 'tcube']
29class IcosphereKindChoice(StringChoice):
30 choices = ['kind1', 'kind2']
33class IcosphereState(ElementState):
34 base = IcosphereBaseChoice.T(default='icosahedron')
35 kind = IcosphereKindChoice.T(default='kind1')
36 level = Int.T(default=0)
37 visible = Bool.T(default=True)
38 smooth = Bool.T(default=False)
39 color = Color.T(default=Color.D('aluminium5'))
41 ambient = Float.T(default=0.0)
42 diffuse = Float.T(default=1.0)
43 specular = Float.T(default=0.0)
45 opacity = Float.T(default=1.0)
46 depth = Float.T(default=30.0*km)
48 def create(self):
49 element = IcosphereElement()
50 return element
53class IcosphereElement(Element):
55 def __init__(self):
56 Element.__init__(self)
57 self._mesh = None
58 self._controls = None
59 self._params = None
61 def get_name(self):
62 return 'Icosphere'
64 def bind_state(self, state):
65 Element.bind_state(self, state)
66 for var in ['visible', 'level', 'base', 'kind', 'smooth', 'color',
67 'ambient', 'diffuse', 'specular', 'depth', 'opacity']:
69 self.register_state_listener3(self.update, state, var)
71 def set_parent(self, parent):
72 Element.set_parent(self, parent)
73 self.register_state_listener3(self.update, self._parent.state, 'dip')
75 self._parent.add_panel(
76 self.get_name(),
77 self._get_controls(),
78 visible=True,
79 title_controls=[
80 self.get_title_control_remove(),
81 self.get_title_control_visible()])
83 self.update()
85 def unset_parent(self):
86 self.unbind_state()
87 if self._parent:
88 if self._mesh:
89 self._parent.remove_actor(self._mesh.actor)
90 self._mesh = None
92 if self._controls:
93 self._parent.remove_panel(self._controls)
94 self._controls = None
96 self._parent.update_view()
97 self._parent = None
99 def update(self, *args):
100 state = self._state
102 params = state.level, state.base, state.kind, state.smooth
104 if self._mesh and (params != self._params or not state.visible):
105 self._parent.remove_actor(self._mesh.actor)
106 self._mesh = None
108 if state.visible and not self._mesh:
109 vertices, faces = icosphere.sphere(
110 state.level, state.base, state.kind, radius=1.0,
111 triangulate=False)
113 self._vertices = vertices
114 self._depth = 0.0
116 self._mesh = TrimeshPipe(vertices, faces, smooth=state.smooth)
117 self._params = params
119 self._parent.add_actor(self._mesh.actor)
121 if self._parent.state.distance < 2.0:
122 angle = 180. - math.acos(self._parent.state.distance / 2.0)*r2d
124 opacity = min(
125 1.0,
126 max(0., (angle+5. - self._parent.state.dip) / 10.))
127 else:
128 opacity = 1.0
130 opacity *= state.opacity
132 if self._mesh:
133 if self._depth != state.depth:
134 radius = (self._parent.planet_radius - state.depth) \
135 / self._parent.planet_radius
137 self._mesh.set_vertices(self._vertices * radius)
138 self._depth = state.depth
140 self._mesh.set_opacity(opacity)
141 self._mesh.set_color(state.color)
142 self._mesh.set_ambient(state.ambient)
143 self._mesh.set_diffuse(state.diffuse)
144 self._mesh.set_specular(state.specular)
146 self._parent.update_view()
148 def _get_controls(self):
149 state = self._state
150 if not self._controls:
151 from ..state import state_bind_slider, \
152 state_bind_combobox, state_bind_checkbox, \
153 state_bind_combobox_color, state_bind_lineedit
155 frame = qw.QFrame()
156 layout = qw.QGridLayout()
157 frame.setLayout(layout)
159 slider = qw.QSlider(qc.Qt.Horizontal)
160 slider.setSizePolicy(
161 qw.QSizePolicy(
162 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
163 slider.setMinimum(0)
164 slider.setMaximum(5)
165 slider.setSingleStep(1)
166 slider.setPageStep(1)
168 layout.addWidget(qw.QLabel('Level'), 0, 0)
169 layout.addWidget(slider, 0, 1)
171 state_bind_slider(self, state, 'level', slider, dtype=int)
173 cb = common.string_choices_to_combobox(IcosphereBaseChoice)
174 layout.addWidget(qw.QLabel('Base'), 1, 0)
175 layout.addWidget(cb, 1, 1)
176 state_bind_combobox(self, state, 'base', cb)
178 cb = common.string_choices_to_combobox(IcosphereKindChoice)
179 layout.addWidget(qw.QLabel('Kind'), 2, 0)
180 layout.addWidget(cb, 2, 1)
181 state_bind_combobox(self, state, 'kind', cb)
183 layout.addWidget(qw.QLabel('Color'), 3, 0)
185 cb = common.strings_to_combobox(
186 ['black', 'aluminium6', 'aluminium5', 'aluminium4',
187 'aluminium3', 'aluminium2', 'aluminium1', 'white',
188 'scarletred2', 'orange2', 'skyblue2', 'plum2'])
190 layout.addWidget(cb, 3, 1)
191 state_bind_combobox_color(
192 self, self._state, 'color', cb)
194 def add_slider(title, param, irow):
195 layout.addWidget(qw.QLabel(title), irow, 0)
197 slider = qw.QSlider(qc.Qt.Horizontal)
198 slider.setSizePolicy(
199 qw.QSizePolicy(
200 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
201 slider.setMinimum(0)
202 slider.setMaximum(1000)
203 layout.addWidget(slider, irow, 1)
205 state_bind_slider(
206 self, state, param, slider, factor=0.001)
208 add_slider('Opacity', 'opacity', 4)
209 add_slider('Ambient', 'ambient', 5)
210 add_slider('Diffuse', 'diffuse', 6)
211 add_slider('Specular', 'specular', 7)
213 cb = qw.QCheckBox('Smooth')
214 layout.addWidget(cb, 8, 1)
215 state_bind_checkbox(self, state, 'smooth', cb)
217 layout.addWidget(qw.QLabel('Depth [km]'), 9, 0)
218 le = qw.QLineEdit()
219 layout.addWidget(le, 9, 1)
220 state_bind_lineedit(
221 self, state, 'depth', le,
222 from_string=lambda s: float(s)*1000.,
223 to_string=lambda v: str(v/1000.))
225 layout.addWidget(qw.QFrame(), 10, 0, 1, 2)
227 self._controls = frame
229 return self._controls
232__all__ = [
233 'IcosphereElement',
234 'IcosphereState',
235 'IcosphereKindChoice',
236 'IcosphereBaseChoice']