diff --git a/fury/actor.py b/fury/actor.py index b7b8ca51e..fffa92974 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -635,3 +635,68 @@ def rhombicuboctahedron( material=material, enable_picking=enable_picking, ) + + +def triangularprism( + centers, + *, + directions=(0, 0, 0), + colors=(1, 1, 1), + scales=(1, 1, 1), + opacity=None, + material="phong", + enable_picking=True, +): + """Visualize one or many triangularprism with different features. + + Parameters + ---------- + centers : ndarray, shape (N, 3) + triangularprism positions. + directions : ndarray, shape (N, 3), optional + The orientation vector of the triangularprism. + colors : ndarray (N,3) or (N, 4) or tuple (3,) or tuple (4,), optional + RGB or RGBA (for opacity) R, G, B and A should be at the range [0, 1]. + scales : int or ndarray (N,3) or tuple (3,), optional + The size of the triangularprism in each dimension. If a single value is + provided, the same size will be used for all triangularprism. + opacity : float, optional + Takes values from 0 (fully transparent) to 1 (opaque). + If both `opacity` and RGBA are provided, the final alpha will be: + final_alpha = alpha_in_RGBA * opacity + material : str, optional + The material type for the triangularprisms. Options are 'phong' and 'basic'. + enable_picking : bool, optional + Whether the triangularprisms should be pickable in a 3D scene. + + Returns + ------- + mesh_actor : Actor + A mesh actor containing the generated triangularprisms, with the specified + material and properties. + + Examples + -------- + >>> from fury import window, actor + >>> import numpy as np + >>> scene = window.Scene() + >>> centers = np.random.rand(5, 3) * 10 + >>> colors = np.random.rand(5, 3) + >>> triangularprism_actor = actor.triangularprism( + centers=centers, colors=colors) + >>> scene.add(triangularprism_actor) + >>> show_manager = window.ShowManager(scene=scene, size=(600, 600)) + >>> show_manager.start() + """ + vertices, faces = fp.prim_triangularprism() + return actor_from_primitive( + vertices, + faces, + centers=centers, + colors=colors, + scales=scales, + directions=directions, + opacity=opacity, + material=material, + enable_picking=enable_picking, + ) diff --git a/fury/tests/test_actor.py b/fury/tests/test_actor.py index ff4a84d54..115b4cb1c 100644 --- a/fury/tests/test_actor.py +++ b/fury/tests/test_actor.py @@ -402,3 +402,60 @@ def test_rhombicuboctahedron(): assert g == 0 and b == 0 assert r == 255 scene.remove(rhombicuboctahedron_actor_2) + + +def test_triangularprism(): + scene = window.Scene() + centers = np.array([[0, 0, 0]]) + colors = np.array([[1, 0, 0]]) + + triangularprism_actor = actor.triangularprism(centers=centers, colors=colors) + scene.add(triangularprism_actor) + + npt.assert_array_equal(triangularprism_actor.local.position, centers[0]) + + mean_vertex = np.mean(triangularprism_actor.geometry.positions.view, axis=0) + npt.assert_array_almost_equal(mean_vertex, centers[0]) + + assert triangularprism_actor.prim_count == 1 + + window.snapshot(scene=scene, fname="triangularprism_test_1.png") + + img = Image.open("triangularprism_test_1.png") + img_array = np.array(img) + + mean_r, mean_g, mean_b, mean_a = np.mean( + img_array.reshape(-1, img_array.shape[2]), axis=0 + ) + + assert mean_r > mean_b and mean_r > mean_g + + middle_pixel = img_array[img_array.shape[0] // 2, img_array.shape[1] // 2] + r, g, b, a = middle_pixel + assert r > g and r > b + assert g == b + scene.remove(triangularprism_actor) + + triangularprism_actor_2 = actor.triangularprism( + centers=centers, colors=colors, material="basic" + ) + scene.add(triangularprism_actor_2) + window.snapshot(scene=scene, fname="triangularprism_test_2.png") + + img = Image.open("triangularprism_test_2.png") + img_array = np.array(img) + + mean_r, mean_g, mean_b, mean_a = np.mean( + img_array.reshape(-1, img_array.shape[2]), axis=0 + ) + + assert mean_r > mean_b and mean_r > mean_g + assert 0 < mean_r < 255 + assert mean_g == 0 and mean_b == 0 + + middle_pixel = img_array[img_array.shape[0] // 2, img_array.shape[1] // 2] + r, g, b, a = middle_pixel + assert r > g and r > b + assert g == 0 and b == 0 + assert r == 255 + scene.remove(triangularprism_actor_2)