diff --git a/pyvista/plotting/plotter.py b/pyvista/plotting/plotter.py index 827b7aeb3b..fe09064ccf 100644 --- a/pyvista/plotting/plotter.py +++ b/pyvista/plotting/plotter.py @@ -1317,6 +1317,11 @@ def add_box_axes(self, *args, **kwargs): # numpydoc ignore=PR01,RT01 """Wrap ``Renderer.add_box_axes``.""" return self.renderer.add_box_axes(*args, **kwargs) + @wraps(Renderer.add_north_arrow_widget) + def add_north_arrow_widget(self, *args, **kwargs): # numpydoc ignore=PR01,RT01 + """Wrap ``Renderer.add_north_arrow_widget``.""" + return self.renderer.add_north_arrow_widget(*args, **kwargs) + @wraps(Renderer.hide_axes) def hide_axes(self, *args, **kwargs): # numpydoc ignore=PR01,RT01 """Wrap ``Renderer.hide_axes``.""" diff --git a/pyvista/plotting/renderer.py b/pyvista/plotting/renderer.py index 759a9e9f63..2b6473d7c8 100644 --- a/pyvista/plotting/renderer.py +++ b/pyvista/plotting/renderer.py @@ -34,6 +34,7 @@ from .render_passes import RenderPasses from .tools import create_axes_marker from .tools import create_axes_orientation_box +from .tools import create_north_arrow from .tools import parse_font_family from .utilities.gl_checks import check_depth_peeling from .utilities.gl_checks import uses_egl @@ -1199,6 +1200,81 @@ def add_axes( axes_widget.SetViewport(viewport) return self.axes_actor + def add_north_arrow_widget( + self, + interactive=None, + color="#4169E1", + opacity=1.0, + line_width=2, + edge_color=None, + lighting=False, + viewport=(0, 0, 0.1, 0.1), + ): + """Add a geographic north arrow to the scene. + + .. versionadded:: 0.44.0 + + Parameters + ---------- + interactive : bool, optional + Control if the orientation widget is interactive. By + default uses the value from + :attr:`pyvista.global_theme.interactive + `. + + color : ColorLike, optional + Color of the north arrow. + + opacity : float, optional + Opacity of the north arrow. + + line_width : float, optional + Width of the north edge arrow lines. + + edge_color : ColorLike, optional + Color of the edges. + + lighting : bool, optional + Enable or disable lighting on north arrow. + + viewport : sequence[float], default: (0, 0, 0.1, 0.1) + Viewport ``(xstart, ystart, xend, yend)`` of the widget. + + Returns + ------- + vtk.vtkOrientationMarkerWidget + Orientation marker widget. + + Examples + -------- + Use an north arrow as the orientation widget. + + >>> import pyvista as pv + >>> from pyvista import examples + >>> terrain = examples.download_st_helens().warp_by_scalar() + >>> pl = pv.Plotter() + >>> actor = pl.add_mesh(terrain) + >>> widget = pl.add_north_arrow_widget() + >>> pl.enable_terrain_style(True) + >>> pl.show() + + """ + marker = create_north_arrow() + mapper = pyvista.DataSetMapper(marker) + actor = pyvista.Actor(mapper) + actor.prop.show_edges = True + if edge_color is not None: + actor.prop.edge_color = edge_color + actor.prop.line_width = line_width + actor.prop.color = color + actor.prop.opacity = opacity + actor.prop.lighting = lighting + return self.add_orientation_widget( + actor, + interactive=interactive, + viewport=viewport, + ) + def add_box_axes( self, *, diff --git a/pyvista/plotting/tools.py b/pyvista/plotting/tools.py index 4fb02bf00e..d36e983f5c 100644 --- a/pyvista/plotting/tools.py +++ b/pyvista/plotting/tools.py @@ -449,6 +449,66 @@ def create_axes_orientation_box( return actor +def create_north_arrow(): + """Create a north arrow mesh. + + .. versionadded:: 0.44.0 + + Returns + ------- + pyvista.PolyData + North arrow mesh. + + """ + points = np.array( + [ + [0.0, 5.0, 0.0], + [-2.0, 0.0, 0.0], + [0.0, 1.5, 0.0], + [2.0, 0.0, 0.0], + [0.0, 5.0, 1.0], + [-2.0, 0.0, 1.0], + [0.0, 1.5, 1.0], + [2.0, 0.0, 1.0], + ], + ) + faces = np.array( + [ + 4, + 3, + 7, + 4, + 0, + 4, + 2, + 6, + 7, + 3, + 4, + 1, + 5, + 6, + 2, + 4, + 0, + 4, + 5, + 1, + 4, + 0, + 1, + 2, + 3, + 4, + 4, + 7, + 6, + 5, + ], + ) + return pyvista.PolyData(points, faces) + + def normalize(x, minimum=None, maximum=None): """ Normalize the given value between [minimum, maximum]. diff --git a/tests/doc/doc_image_cache/pyvista-Plotter-add_north_arrow_widget-1_00_00.jpg b/tests/doc/doc_image_cache/pyvista-Plotter-add_north_arrow_widget-1_00_00.jpg new file mode 100644 index 0000000000..6f4e3e62a1 Binary files /dev/null and b/tests/doc/doc_image_cache/pyvista-Plotter-add_north_arrow_widget-1_00_00.jpg differ diff --git a/tests/doc/doc_image_cache/pyvista-Renderer-add_north_arrow_widget-1_00_00.jpg b/tests/doc/doc_image_cache/pyvista-Renderer-add_north_arrow_widget-1_00_00.jpg new file mode 100644 index 0000000000..6f4e3e62a1 Binary files /dev/null and b/tests/doc/doc_image_cache/pyvista-Renderer-add_north_arrow_widget-1_00_00.jpg differ diff --git a/tests/plotting/image_cache/add_north_arrow.png b/tests/plotting/image_cache/add_north_arrow.png new file mode 100644 index 0000000000..677443e5f9 Binary files /dev/null and b/tests/plotting/image_cache/add_north_arrow.png differ diff --git a/tests/plotting/test_plotting.py b/tests/plotting/test_plotting.py index e045c42a91..2ed76cf2c2 100644 --- a/tests/plotting/test_plotting.py +++ b/tests/plotting/test_plotting.py @@ -1227,6 +1227,13 @@ def test_add_box_axes(): plotter.show() +def test_add_north_arrow(): + plotter = pv.Plotter() + plotter.add_north_arrow_widget(viewport=(0, 0, 0.5, 0.5)) + plotter.add_mesh(pv.Arrow(direction=(0, 1, 0))) + plotter.show() + + def test_screenshot(tmpdir): plotter = pv.Plotter() plotter.add_mesh(pv.Sphere())