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
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-04 09:52 +0000
1import vtk
2import numpy as num
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
11from .base import Element, ElementState
13guts_prefix = 'sparrow'
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)
25 return lines_ned
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)
37 return lines_ned
40class Crosshair(object):
41 def __init__(self):
43 self.mapper_surface = vtk.vtkDataSetMapper()
44 self.mapper_position = vtk.vtkDataSetMapper()
46 self.actor_surface = vtk.vtkActor()
47 self.actor_surface.SetMapper(self.mapper_surface)
49 self.actor_position = vtk.vtkActor()
50 self.actor_position.SetMapper(self.mapper_position)
52 self._color = None
53 self.set_color(Color('white'))
55 def get_actors(self):
56 return [self.actor_surface, self.actor_position]
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
68 line_lld[:, 2] = line_ned_sized[:, 2]
69 lines_lld.append(line_lld)
71 mpl_surface = vtk_util.make_multi_polyline(
72 lines_latlondepth=lines_lld)
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
83 line_lld[:, 2] = depth + line_ned_sized[:, 2]
84 lines_lld.append(line_lld)
86 mpl_position = vtk_util.make_multi_polyline(
87 lines_latlondepth=lines_lld)
89 return [mpl_surface, mpl_position]
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)
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)
105 self._color = color
108class CrosshairState(ElementState):
109 visible = Bool.T(default=False)
110 color = Color.T(default=Color.D('white'))
112 def __init__(self, *args, **kwargs):
113 ElementState.__init__(self, *args, **kwargs)
114 self.is_connected = False
116 def create(self):
117 element = CrosshairElement()
118 return element
121class CrosshairElement(Element):
123 def __init__(self):
124 Element.__init__(self)
125 self._controls = None
126 self._crosshair = None
128 def get_name(self):
129 return 'Crosshair'
131 def bind_state(self, state):
132 Element.bind_state(self, state)
133 self.talkie_connect(state, ['visible', 'color'], self.update)
135 def set_parent(self, parent):
136 Element.set_parent(self, parent)
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()])
145 self.talkie_connect(
146 self._parent.state, ['distance', 'lat', 'lon'], self.update)
148 self.update()
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
157 if self._controls:
158 self._parent.remove_panel(self._controls)
159 self._controls = None
161 self._parent.update_view()
162 self._parent = None
164 def update(self, *args):
165 state = self._state
166 pstate = self._parent.state
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)
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)
179 else:
180 if self._crosshair:
181 for actor in self._crosshair.get_actors():
182 self._parent.remove_actor(actor)
184 self._crosshair = None
186 self._parent.update_view()
188 def _get_controls(self):
189 if not self._controls:
190 from ..state import state_bind_combobox_color
192 frame = qw.QFrame()
193 layout = qw.QGridLayout()
194 frame.setLayout(layout)
196 # color
198 layout.addWidget(qw.QLabel('Color'), 0, 0)
200 cb = common.strings_to_combobox(
201 ['black', 'white', 'scarletred2'])
203 layout.addWidget(cb, 0, 1)
204 state_bind_combobox_color(self, self._state, 'color', cb)
206 layout.addWidget(qw.QFrame(), 2, 0, 1, 2)
208 self._controls = frame
210 return self._controls
213__all__ = [
214 'CrosshairElement',
215 'CrosshairState']