@@ -2808,6 +2808,79 @@ def hover_idx_callback(data):
28082808 """
28092809 self ._register_callback ("hover_idx_change" , callback , remove = remove )
28102810
2811+ """
2812+ Custom utils
2813+ """
2814+
2815+ def scene_extents_min_max (self , is_slice_mm : bool = True ) -> tuple :
2816+ """
2817+ Return the scene's min, max, and range extents in mm or voxel space.
2818+
2819+ Includes both volume and mesh geometry.
2820+
2821+ Parameters
2822+ ----------
2823+ is_slice_mm : bool, optional
2824+ If True, returns extents in mm space.
2825+ If False, returns extents in voxel space. Default is True.
2826+
2827+ Returns
2828+ -------
2829+ tuple
2830+ A tuple containing three lists:
2831+ - min_extents: [x, y, z] minimum coordinates
2832+ - max_extents: [x, y, z] maximum coordinates
2833+ - range: [x, y, z] range (max - min) for each dimension
2834+
2835+ Raises
2836+ ------
2837+ RuntimeError
2838+ If volumes exist but volume_object_3d_data is not defined.
2839+
2840+ Examples
2841+ --------
2842+ ::
2843+
2844+ min_ext, max_ext, range_ext = nv.scene_extents_min_max()
2845+ print(f"Min: {min_ext}, Max: {max_ext}, Range: {range_ext}")
2846+ """
2847+ mn = np .array ([0.0 , 0.0 , 0.0 ])
2848+ mx = np .array ([0.0 , 0.0 , 0.0 ])
2849+
2850+ if len (self .volumes ) > 0 :
2851+ if not self ._volume_object_3d_data :
2852+ raise RuntimeError (
2853+ "_volume_object_3d_data not defined. Canvas needs to be attached."
2854+ )
2855+
2856+ if is_slice_mm :
2857+ mn = np .array (self ._volume_object_3d_data .extents_min )
2858+ mx = np .array (self ._volume_object_3d_data .extents_max )
2859+ else :
2860+ if (
2861+ self .volumes [0 ].extents_min_ortho
2862+ and self .volumes [0 ].extents_max_ortho
2863+ ):
2864+ mn = np .array (self .volumes [0 ].extents_min_ortho )
2865+ mx = np .array (self .volumes [0 ].extents_max_ortho )
2866+
2867+ if len (self .meshes ) > 0 :
2868+ if len (self .volumes ) < 1 :
2869+ if self .meshes [0 ].extents_min and self .meshes [0 ].extents_max :
2870+ mn = np .array (self .meshes [0 ].extents_min )
2871+ mx = np .array (self .meshes [0 ].extents_max )
2872+
2873+ for mesh in self .meshes :
2874+ if mesh .extents_min and mesh .extents_max :
2875+ mesh_min = np .array (mesh .extents_min )
2876+ mesh_max = np .array (mesh .extents_max )
2877+ mn = np .minimum (mn , mesh_min )
2878+ mx = np .maximum (mx , mesh_max )
2879+
2880+ range_extents = mx - mn
2881+
2882+ return (mn .tolist (), mx .tolist (), range_extents .tolist ())
2883+
28112884
28122885class WidgetObserver :
28132886 """Creates an observer on the `attribute` of `object` for a `widget`."""
0 commit comments