From 39f9d88c8fd3fdb20bbc490db294b2d8bbb09d37 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 5 Feb 2024 09:38:30 +0100 Subject: [PATCH] Remove scaling of highlight width, fix showing shapes for uneven coordinates (#6629) # References and relevant issues This PR is created as result of debug https://github.com/napari/napari/issues/6627#issuecomment-1914804363 As 0.4.19 branch has fewer problems than #6628 is created for 0.4.19. # Description Fix logic for selecting of visible shapes based on idea from #2289. It is lucky that we do not hit this earlier. Removes scaling of width of markers border (this is same like in #6628) To improve readability, this update `ShapesVisual` to have named subvisuals. --- napari/_vispy/layers/shapes.py | 20 ++++++++++---------- napari/_vispy/visuals/shapes.py | 25 +++++++++++++++++++++++++ napari/layers/shapes/_shape_list.py | 4 +++- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/napari/_vispy/layers/shapes.py b/napari/_vispy/layers/shapes.py index 84e6a59ed3a..07bce048d19 100644 --- a/napari/_vispy/layers/shapes.py +++ b/napari/_vispy/layers/shapes.py @@ -9,6 +9,8 @@ class VispyShapesLayer(VispyBaseLayer): + node: ShapesVisual + def __init__(self, layer) -> None: node = ShapesVisual() super().__init__(layer, node) @@ -20,8 +22,8 @@ def __init__(self, layer) -> None: self.layer.text.events.connect(self._on_text_change) # TODO: move to overlays - self.node._subvisuals[3].symbol = 'square' - self.node._subvisuals[3].scaling = False + self.node.highlight_vertices.symbol = 'square' + self.node.highlight_vertices.scaling = False self.reset() self._on_data_change() @@ -48,7 +50,7 @@ def _on_data_change(self): ): vertices = np.pad(vertices, ((0, 0), (0, 1)), mode='constant') - self.node._subvisuals[0].set_data( + self.node.shape_faces.set_data( vertices=vertices, faces=faces, face_colors=colors ) @@ -68,7 +70,7 @@ def _on_highlight_change(self): vertices = np.zeros((3, self.layer._slice_input.ndisplay)) faces = np.array([[0, 1, 2]]) - self.node._subvisuals[1].set_data( + self.node.shape_highlights.set_data( vertices=vertices, faces=faces, color=self.layer._highlight_color, @@ -84,8 +86,7 @@ def _on_highlight_change(self): _, ) = self.layer._compute_vertices_and_box() - # use last dimension of scale like (thickness cannot be anisotropic) - width = settings.appearance.highlight_thickness / self.layer.scale[-1] + width = settings.appearance.highlight_thickness if vertices is None or len(vertices) == 0: vertices = np.zeros((1, self.layer._slice_input.ndisplay)) @@ -93,7 +94,7 @@ def _on_highlight_change(self): else: size = self.layer._vertex_size - self.node._subvisuals[3].set_data( + self.node.highlight_vertices.set_data( vertices, size=size, face_color=face_color, @@ -105,7 +106,7 @@ def _on_highlight_change(self): pos = np.zeros((1, self.layer._slice_input.ndisplay)) width = 0 - self.node._subvisuals[2].set_data( + self.node.highlight_lines.set_data( pos=pos, color=edge_color, width=width ) @@ -123,8 +124,7 @@ def _update_text(self, *, update_node=True): def _get_text_node(self): """Function to get the text node from the Compound visual""" - text_node = self.node._subvisuals[-1] - return text_node + return self.node.text def _on_text_change(self, event=None): if event is not None: diff --git a/napari/_vispy/visuals/shapes.py b/napari/_vispy/visuals/shapes.py index 23bd913b55f..3d92dfe7ecf 100644 --- a/napari/_vispy/visuals/shapes.py +++ b/napari/_vispy/visuals/shapes.py @@ -18,3 +18,28 @@ class ShapesVisual(ClippingPlanesMixin, Compound): def __init__(self) -> None: super().__init__([Mesh(), Mesh(), Line(), Markers(), Text()]) + + @property + def shape_faces(self) -> Mesh: + """Mesh for shape faces""" + return self._subvisuals[0] + + @property + def shape_highlights(self) -> Mesh: + """Mesh for shape highlights""" + return self._subvisuals[1] + + @property + def highlight_lines(self) -> Line: + """Lines for shape highlights""" + return self._subvisuals[2] + + @property + def highlight_vertices(self) -> Markers: + """Vertices for shape highlights""" + return self._subvisuals[3] + + @property + def text(self) -> Text: + """Text labels""" + return self._subvisuals[4] diff --git a/napari/layers/shapes/_shape_list.py b/napari/layers/shapes/_shape_list.py index c8483d9d51c..aa047b3487a 100644 --- a/napari/layers/shapes/_shape_list.py +++ b/napari/layers/shapes/_shape_list.py @@ -271,7 +271,9 @@ def _update_displayed(self): # Slice key must exactly match mins and maxs of shape as then the # shape is entirely contained within the current slice. if len(self.shapes) > 0: - self._displayed = np.all(self.slice_keys == slice_key, axis=(1, 2)) + self._displayed = np.all( + np.abs(self.slice_keys - slice_key) < 0.5, axis=(1, 2) + ) else: self._displayed = np.array([]) disp_indices = np.where(self._displayed)[0]