diff options
Diffstat (limited to 'silx/gui/plot3d/items/_pick.py')
-rw-r--r-- | silx/gui/plot3d/items/_pick.py | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/silx/gui/plot3d/items/_pick.py b/silx/gui/plot3d/items/_pick.py deleted file mode 100644 index 0d6a495..0000000 --- a/silx/gui/plot3d/items/_pick.py +++ /dev/null @@ -1,265 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2018-2020 European Synchrotron Radiation Facility -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# ###########################################################################*/ -"""This module provides classes supporting item picking. -""" - -from __future__ import absolute_import - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "24/09/2018" - -import logging -import numpy - -from ...plot.items._pick import PickingResult as _PickingResult -from ..scene import Viewport, Base - - -_logger = logging.getLogger(__name__) - - -class PickContext(object): - """Store information related to current picking - - :param int x: Widget coordinate - :param int y: Widget coordinate - :param ~silx.gui.plot3d.scene.Viewport viewport: - Viewport where picking occurs - :param Union[None,callable] condition: - Test whether each item needs to be picked or not. - """ - - def __init__(self, x, y, viewport, condition): - self._widgetPosition = x, y - assert isinstance(viewport, Viewport) - self._viewport = viewport - self._ndcZRange = -1., 1. - self._enabled = True - self._condition = condition - - def copy(self): - """Returns a copy - - :rtype: PickContent - """ - x, y = self.getWidgetPosition() - context = PickContext(x, y, self.getViewport(), self._condition) - context.setNDCZRange(*self._ndcZRange) - context.setEnabled(self.isEnabled()) - return context - - def isItemPickable(self, item): - """Check condition for the given item. - - :param Item3D item: - :return: Whether to process the item (True) or to skip it (False) - :rtype: bool - """ - return self._condition is None or self._condition(item) - - def getViewport(self): - """Returns viewport where picking occurs - - :rtype: ~silx.gui.plot3d.scene.Viewport - """ - return self._viewport - - def getWidgetPosition(self): - """Returns (x, y) position in pixel in the widget - - Origin is at the top-left corner of the widget, - X from left to right, Y goes downward. - - :rtype: List[int] - """ - return self._widgetPosition - - def setEnabled(self, enabled): - """Set whether picking is enabled or not - - :param bool enabled: True to enable picking, False otherwise - """ - self._enabled = bool(enabled) - - def isEnabled(self): - """Returns True if picking is currently enabled, False otherwise. - - :rtype: bool - """ - return self._enabled - - def setNDCZRange(self, near=-1., far=1.): - """Set near and far Z value in normalized device coordinates - - This allows to clip the ray to a subset of the NDC range - - :param float near: Near segment end point Z coordinate - :param float far: Far segment end point Z coordinate - """ - self._ndcZRange = near, far - - def getNDCPosition(self): - """Return Normalized device coordinates of picked point. - - :return: (x, y) in NDC coordinates or None if outside viewport. - :rtype: Union[None,List[float]] - """ - if not self.isEnabled(): - return None - - # Convert x, y from window to NDC - x, y = self.getWidgetPosition() - return self.getViewport().windowToNdc(x, y, checkInside=True) - - def getPickingSegment(self, frame): - """Returns picking segment in requested coordinate frame. - - :param Union[str,Base] frame: - The frame in which to get the picking segment, - either a keyword: 'ndc', 'camera', 'scene' or a scene - :class:`~silx.gui.plot3d.scene.Base` object. - :return: Near and far points of the segment as (x, y, z, w) - or None if picked point is outside viewport - :rtype: Union[None,numpy.ndarray] - """ - assert frame in ('ndc', 'camera', 'scene') or isinstance(frame, Base) - - positionNdc = self.getNDCPosition() - if positionNdc is None: - return None - - near, far = self._ndcZRange - rayNdc = numpy.array((positionNdc + (near, 1.), - positionNdc + (far, 1.)), - dtype=numpy.float64) - if frame == 'ndc': - return rayNdc - - viewport = self.getViewport() - - rayCamera = viewport.camera.intrinsic.transformPoints( - rayNdc, - direct=False, - perspectiveDivide=True) - if frame == 'camera': - return rayCamera - - rayScene = viewport.camera.extrinsic.transformPoints( - rayCamera, direct=False) - if frame == 'scene': - return rayScene - - # frame is a scene Base object - rayObject = frame.objectToSceneTransform.transformPoints( - rayScene, direct=False) - return rayObject - - -class PickingResult(_PickingResult): - """Class to access picking information in a 3D scene.""" - - def __init__(self, item, positions, indices=None, fetchdata=None): - """Init - - :param ~silx.gui.plot3d.items.Item3D item: The picked item - :param numpy.ndarray positions: - Nx3 array-like of picked positions (x, y, z) in item coordinates. - :param numpy.ndarray indices: Array-like of indices of picked data. - Either 1D or 2D with dim0: data dimension and dim1: indices. - No copy is made. - :param callable fetchdata: Optional function with a bool copy argument - to provide an alternative function to access item data. - Default is to use `item.getData`. - """ - super(PickingResult, self).__init__(item, indices) - - self._objectPositions = numpy.array( - positions, copy=False, dtype=numpy.float64) - - # Store matrices to generate positions on demand - primitive = item._getScenePrimitive() - self._objectToSceneTransform = primitive.objectToSceneTransform - self._objectToNDCTransform = primitive.objectToNDCTransform - self._scenePositions = None - self._ndcPositions = None - - self._fetchdata = fetchdata - - def getData(self, copy=True): - """Returns picked data values - - :param bool copy: True (default) to get a copy, - False to return internal arrays - :rtype: Union[None,numpy.ndarray] - """ - - indices = self.getIndices(copy=False) - if indices is None or len(indices) == 0: - return None - - item = self.getItem() - if self._fetchdata is None: - if hasattr(item, 'getData'): - data = item.getData(copy=False) - else: - return None - else: - data = self._fetchdata(copy=False) - - return numpy.array(data[indices], copy=copy) - - def getPositions(self, frame='scene', copy=True): - """Returns picking positions in item coordinates. - - :param str frame: The frame in which the positions are returned - Either 'scene' for world space, - 'ndc' for normalized device coordinates or 'object' for item frame. - :param bool copy: True (default) to get a copy, - False to return internal arrays - :return: Nx3 array of (x, y, z) coordinates - :rtype: numpy.ndarray - """ - if frame == 'ndc': - if self._ndcPositions is None: # Lazy-loading - self._ndcPositions = self._objectToNDCTransform.transformPoints( - self._objectPositions, perspectiveDivide=True) - - positions = self._ndcPositions - - elif frame == 'scene': - if self._scenePositions is None: # Lazy-loading - self._scenePositions = self._objectToSceneTransform.transformPoints( - self._objectPositions) - - positions = self._scenePositions - - elif frame == 'object': - positions = self._objectPositions - - else: - raise ValueError('Unsupported frame argument: %s' % str(frame)) - - return numpy.array(positions, copy=copy) |