Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/gui/sparrow/elements/coastlines.py: 93%
153 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 15:01 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 15:01 +0000
1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import numpy as num
7import vtk
9from pyrocko.guts import Bool, StringChoice, Float
10from pyrocko.gui.qt_compat import qw, qc
11from pyrocko.color import Color
14from pyrocko.gui import vtk_util
15from .. import common
16from .base import Element, ElementState
18guts_prefix = 'sparrow'
21class CoastlineResolutionChoice(StringChoice):
22 choices = [
23 'crude',
24 'low',
25 'intermediate',
26 'high',
27 'full']
30class CoastlinesPipe(object):
31 def __init__(self, resolution='low'):
33 self.mapper = vtk.vtkDataSetMapper()
34 self.plane = vtk.vtkPlane()
35 self.plane.SetOrigin(0.0, 0.0, 0.0)
36 coll = vtk.vtkPlaneCollection()
37 coll.AddItem(self.plane)
38 self.mapper.SetClippingPlanes(coll)
40 self._polyline_grid = {}
41 self._opacity = 1.0
42 self._line_width = 1.0
43 self._color = Color('white')
44 self.set_resolution(resolution)
46 actor = vtk.vtkActor()
47 actor.SetMapper(self.mapper)
49 prop = actor.GetProperty()
50 prop.SetDiffuseColor(1, 1, 1)
52 self.prop = prop
53 self.actor = actor
55 def set_resolution(self, resolution):
56 assert resolution in CoastlineResolutionChoice.choices
58 if resolution not in self._polyline_grid:
59 pb = common.get_viewer().progressbars
60 if pb:
61 mess = 'Loading %s resolution coastlines' % resolution
62 pb.set_status(mess, 0, can_abort=False)
64 from pyrocko.dataset.gshhg import GSHHG
65 g = getattr(GSHHG, resolution)()
67 lines = []
68 npoly = len(g.polygons)
69 for ipoly, poly in enumerate(g.polygons):
70 if pb:
71 pb.set_status(
72 mess, float(ipoly) / npoly * 100., can_abort=False)
74 lines.append(poly.points)
76 self._polyline_grid[resolution] = vtk_util.make_multi_polyline(
77 lines_latlon=lines, depth=-200.)
79 if pb:
80 pb.set_status(mess, 100, can_abort=False)
82 vtk_util.vtk_set_input(self.mapper, self._polyline_grid[resolution])
84 def set_opacity(self, opacity):
85 opacity = float(opacity)
86 if self._opacity != opacity:
87 self.prop.SetOpacity(opacity)
88 self._opacity = opacity
90 def set_color(self, color):
91 if self._color != color:
92 self.prop.SetDiffuseColor(color.rgb)
93 self._color = color
95 def set_line_width(self, width):
96 width = float(width)
97 if self._line_width != width:
98 self.prop.SetLineWidth(width)
99 self._line_width = width
101 def set_clipping_plane(self, origin, normal):
102 self.plane.SetOrigin(*origin)
103 self.plane.SetNormal(*normal)
106class CoastlinesState(ElementState):
107 visible = Bool.T(default=True)
108 resolution = CoastlineResolutionChoice.T(default='low')
109 opacity = Float.T(default=0.4)
110 color = Color.T(default=Color.D('white'))
111 line_width = Float.T(default=1.0)
113 def create(self):
114 element = CoastlinesElement()
115 return element
118class CoastlinesElement(Element):
120 def __init__(self):
121 Element.__init__(self)
122 self._parent = None
123 self._controls = None
124 self._coastlines = None
126 def get_name(self):
127 return 'Coastlines'
129 def bind_state(self, state):
130 Element.bind_state(self, state)
131 self.talkie_connect(
132 state,
133 ['visible', 'resolution', 'opacity', 'color', 'line_width'],
134 self.update)
136 def set_parent(self, parent):
137 self._parent = parent
138 self._parent.add_panel(
139 self.get_title_label(),
140 self._get_controls(),
141 visible=True,
142 title_controls=[
143 self.get_title_control_remove(),
144 self.get_title_control_visible()])
146 self.talkie_connect(
147 self._parent.state,
148 ['lat', 'lon', 'depth', 'distance', 'azimuth', 'dip'],
149 self.update_clipping)
151 self.update()
152 self.update_clipping()
154 def unset_parent(self):
155 self.unbind_state()
156 if self._parent:
157 if self._coastlines:
158 self._parent.remove_actor(self._coastlines.actor)
159 self._coastlines = None
161 if self._controls:
162 self._parent.remove_panel(self._controls)
163 self._controls = None
165 self._parent.update_view()
166 self._parent = None
168 def update(self, *args):
169 state = self._state
170 if not state.visible and self._coastlines:
171 self._parent.remove_actor(self._coastlines.actor)
173 if state.visible:
174 if not self._coastlines:
175 self._coastlines = CoastlinesPipe(resolution=state.resolution)
177 self._parent.add_actor(self._coastlines.actor)
178 self._coastlines.set_resolution(state.resolution)
179 self._coastlines.set_opacity(state.opacity)
180 self._coastlines.set_color(state.color)
181 self._coastlines.set_line_width(state.line_width)
183 self._parent.update_view()
185 def update_clipping(self, *args):
186 if self._state.visible and self._coastlines:
187 cam = self._parent.camera_params[0]
188 origin = cam / num.linalg.norm(cam)**2
189 self._coastlines.set_clipping_plane(origin, cam)
191 def _get_controls(self):
192 if not self._controls:
193 from ..state import state_bind_combobox, \
194 state_bind_slider, state_bind_combobox_color
196 frame = qw.QFrame()
197 layout = qw.QGridLayout()
198 frame.setLayout(layout)
200 layout.addWidget(qw.QLabel('Resolution'), 0, 0)
202 cb = common.string_choices_to_combobox(CoastlineResolutionChoice)
203 layout.addWidget(cb, 0, 1)
204 state_bind_combobox(self, self._state, 'resolution', cb)
206 # opacity
208 layout.addWidget(qw.QLabel('Opacity'), 1, 0)
210 slider = qw.QSlider(qc.Qt.Horizontal)
211 slider.setSizePolicy(
212 qw.QSizePolicy(
213 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
214 slider.setMinimum(0)
215 slider.setMaximum(1000)
216 layout.addWidget(slider, 1, 1)
218 state_bind_slider(
219 self, self._state, 'opacity', slider, factor=0.001)
221 # color
223 layout.addWidget(qw.QLabel('Color'), 2, 0)
225 cb = common.strings_to_combobox(
226 ['black', 'white'])
228 layout.addWidget(cb, 2, 1)
229 state_bind_combobox_color(
230 self, self._state, 'color', cb)
232 layout.addWidget(qw.QLabel('Line width'), 3, 0)
234 slider = qw.QSlider(qc.Qt.Horizontal)
235 slider.setSizePolicy(
236 qw.QSizePolicy(
237 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
238 slider.setMinimum(0)
239 slider.setMaximum(100)
240 layout.addWidget(slider, 3, 1)
241 state_bind_slider(
242 self, self._state, 'line_width', slider, factor=0.1)
244 layout.addWidget(qw.QFrame(), 5, 0, 1, 2)
246 self._controls = frame
248 return self._controls
251__all__ = [
252 'CoastlinesElement',
253 'CoastlinesState']