Source code for pyrocko.gui.sparrow.elements.crosshair

import vtk
import numpy as num

from pyrocko.gui.qt_compat import qw
from pyrocko import orthodrome as od
from pyrocko.gui import vtk_util
from pyrocko.guts import Bool
from pyrocko.color import Color
from .. import common

from .base import Element, ElementState

guts_prefix = 'sparrow'


def cross3d_flat(a=1., b=0.5):
    lines_ned = []
    for i in range(2):
        for s in (-1., 1.):
            line = num.zeros((2, 3))
            line[0, i] = s*a
            line[1, i] = s*b
            lines_ned.append(line)

    return lines_ned


def cross3d(a=1., b=0.5):
    lines_ned = []
    for i in range(3):
        for s in (-1., 1.):
            line = num.zeros((2, 3))
            line[0, i] = s*a
            line[1, i] = s*b
            lines_ned.append(line)

    return lines_ned


class Crosshair(object):
    def __init__(self):

        self.mapper_surface = vtk.vtkDataSetMapper()
        self.mapper_position = vtk.vtkDataSetMapper()

        self.actor_surface = vtk.vtkActor()
        self.actor_surface.SetMapper(self.mapper_surface)

        self.actor_position = vtk.vtkActor()
        self.actor_position.SetMapper(self.mapper_position)

        self._color = None
        self.set_color(Color('white'))

    def get_actors(self):
        return [self.actor_surface, self.actor_position]

    def make_multi_polyline(self, lat, lon, depth, size):
        lines_ned = cross3d_flat()
        lines_lld = []
        for line_ned in lines_ned:
            line_ned_sized = size * line_ned
            line_lld = num.zeros(line_ned.shape)
            line_lld[:, :2] = num.vstack(
                od.ne_to_latlon(
                    lat, lon, line_ned_sized[:, 0], line_ned_sized[:, 1])).T

            line_lld[:, 2] = line_ned_sized[:, 2]
            lines_lld.append(line_lld)

        mpl_surface = vtk_util.make_multi_polyline(
            lines_latlondepth=lines_lld)

        lines_ned = cross3d()
        lines_lld = []
        for line_ned in lines_ned:
            line_ned_sized = size * line_ned
            line_lld = num.zeros(line_ned.shape)
            line_lld[:, :2] = num.vstack(
                od.ne_to_latlon(
                    lat, lon, line_ned_sized[:, 0], line_ned_sized[:, 1])).T

            line_lld[:, 2] = depth + line_ned_sized[:, 2]
            lines_lld.append(line_lld)

        mpl_position = vtk_util.make_multi_polyline(
            lines_latlondepth=lines_lld)

        return [mpl_surface, mpl_position]

    def set_geometry(self, lat, lon, depth, size):
        mpl_surface, mpl_position = self.make_multi_polyline(
            lat, lon, depth, size)
        vtk_util.vtk_set_input(self.mapper_surface, mpl_surface)
        vtk_util.vtk_set_input(self.mapper_position, mpl_position)
        self.actor_surface.GetProperty().SetOpacity(
            min(1.0, abs(depth) / size) * 0.5)

    def set_color(self, color):
        if self._color is None or self._color != color:
            for actor in self.get_actors():
                prop = actor.GetProperty()
                prop.SetDiffuseColor(color.rgb)

            self._color = color


[docs]class CrosshairState(ElementState): visible = Bool.T(default=False) color = Color.T(default=Color.D('white')) def __init__(self, *args, **kwargs): ElementState.__init__(self, *args, **kwargs) self.is_connected = False def create(self): element = CrosshairElement() return element
class CrosshairElement(Element): def __init__(self): Element.__init__(self) self._controls = None self._crosshair = None def get_name(self): return 'Crosshair' def bind_state(self, state): Element.bind_state(self, state) self.talkie_connect(state, ['visible', 'color'], self.update) def set_parent(self, parent): Element.set_parent(self, parent) self._parent.add_panel( self.get_title_label(), self._get_controls(), visible=False, title_controls=[ self.get_title_control_visible()]) self.talkie_connect( self._parent.state, ['distance', 'lat', 'lon'], self.update) self.update() def unset_parent(self): self.unbind_state() if self._parent: if self._crosshair: self._parent.remove_actor(self._crosshair.actor) self._crosshair = None if self._controls: self._parent.remove_panel(self._controls) self._controls = None self._parent.update_view() self._parent = None def update(self, *args): state = self._state pstate = self._parent.state if state.visible: if not self._crosshair: self._crosshair = Crosshair() for actor in self._crosshair.get_actors(): self._parent.add_actor(actor) size = pstate.distance * 100.*1000. self._crosshair.set_geometry( pstate.lat, pstate.lon, pstate.depth, size) self._crosshair.set_color(state.color) else: if self._crosshair: for actor in self._crosshair.get_actors(): self._parent.remove_actor(actor) self._crosshair = None self._parent.update_view() def _get_controls(self): if not self._controls: from ..state import state_bind_combobox_color frame = qw.QFrame() layout = qw.QGridLayout() frame.setLayout(layout) # color layout.addWidget(qw.QLabel('Color'), 0, 0) cb = common.strings_to_combobox( ['black', 'white', 'scarletred2']) layout.addWidget(cb, 0, 1) state_bind_combobox_color(self, self._state, 'color', cb) layout.addWidget(qw.QFrame(), 2, 0, 1, 2) self._controls = frame return self._controls __all__ = [ 'CrosshairElement', 'CrosshairState']