Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NF: All shape actor based on primitive #967

Open
wants to merge 11 commits into
base: v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions fury/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,3 +441,131 @@ def frustum(
material=material,
enable_picking=enable_picking,
)


def tetrahedron(
centers,
*,
directions=(0, 0, 0),
colors=(1, 1, 1),
scales=(1, 1, 1),
opacity=None,
material="phong",
enable_picking=True,
):
"""Visualize one or many tetrahedrons with different features.

Parameters
----------
centers : ndarray, shape (N, 3)
tetrahedron positions.
directions : ndarray, shape (N, 3), optional
The orientation vector of the tetrahedron.
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 tetrahedron in each dimension. If a single value is provided,
the same size will be used for all tetrahedron.
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 tetrahedrons. Options are 'phong' and 'basic'.
enable_picking : bool, optional
Whether the tetrahedrons should be pickable in a 3D scene.

Returns
-------
mesh_actor : Actor
A mesh actor containing the generated tetrahedrons, 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)
>>> tetrahedron_actor = actor.tetrahedron(centers=centers, colors=colors)
>>> scene.add(tetrahedron_actor)
>>> show_manager = window.ShowManager(scene=scene, size=(600, 600))
>>> show_manager.start()
"""
vertices, faces = fp.prim_tetrahedron()
return actor_from_primitive(
vertices,
faces,
centers=centers,
colors=colors,
scales=scales,
directions=directions,
opacity=opacity,
material=material,
enable_picking=enable_picking,
)


def icosahedron(
centers,
*,
directions=(0, 0, 0),
colors=(1, 1, 1),
scales=(1, 1, 1),
opacity=None,
material="phong",
enable_picking=True,
):
"""Visualize one or many icosahedrons with different features.

Parameters
----------
centers : ndarray, shape (N, 3)
icosahedron positions.
directions : ndarray, shape (N, 3), optional
The orientation vector of the icosahedron.
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 icosahedron in each dimension. If a single value is provided,
the same size will be used for all icosahedron.
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 icosahedrons. Options are 'phong' and 'basic'.
enable_picking : bool, optional
Whether the icosahedrons should be pickable in a 3D scene.

Returns
-------
mesh_actor : Actor
A mesh actor containing the generated icosahedrons, 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)
>>> icosahedron_actor = actor.icosahedron(centers=centers, colors=colors)
>>> scene.add(icosahedron_actor)
>>> show_manager = window.ShowManager(scene=scene, size=(600, 600))
>>> show_manager.start()
"""
vertices, faces = fp.prim_icosahedron()
return actor_from_primitive(
vertices,
faces,
centers=centers,
colors=colors,
scales=scales,
directions=directions,
opacity=opacity,
material=material,
enable_picking=enable_picking,
)
114 changes: 114 additions & 0 deletions fury/tests/test_actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,117 @@ def test_frustum():
assert g == 0 and b == 0
assert r == 255
scene.remove(frustum_actor_2)


def test_tetrahedron():
scene = window.Scene()
centers = np.array([[0, 0, 0]])
colors = np.array([[1, 0, 0]])

tetrahedron_actor = actor.tetrahedron(centers=centers, colors=colors)
scene.add(tetrahedron_actor)

npt.assert_array_equal(tetrahedron_actor.local.position, centers[0])

mean_vertex = np.mean(tetrahedron_actor.geometry.positions.view, axis=0)
npt.assert_array_almost_equal(mean_vertex, centers[0])

assert tetrahedron_actor.prim_count == 1

window.snapshot(scene=scene, fname="tetrahedron_test_1.png")

img = Image.open("tetrahedron_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(tetrahedron_actor)

tetrahedron_actor_2 = actor.tetrahedron(
centers=centers, colors=colors, material="basic"
)
scene.add(tetrahedron_actor_2)
window.snapshot(scene=scene, fname="tetrahedron_test_2.png")

img = Image.open("tetrahedron_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(tetrahedron_actor_2)


def test_icosahedron():
scene = window.Scene()
centers = np.array([[0, 0, 0]])
colors = np.array([[1, 0, 0]])

icosahedron_actor = actor.icosahedron(centers=centers, colors=colors)
scene.add(icosahedron_actor)

npt.assert_array_equal(icosahedron_actor.local.position, centers[0])

mean_vertex = np.mean(icosahedron_actor.geometry.positions.view, axis=0)
npt.assert_array_almost_equal(mean_vertex, centers[0])

assert icosahedron_actor.prim_count == 1

window.snapshot(scene=scene, fname="icosahedron_test_1.png")

img = Image.open("icosahedron_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(icosahedron_actor)

icosahedron_actor_2 = actor.icosahedron(
centers=centers, colors=colors, material="basic"
)
scene.add(icosahedron_actor_2)
window.snapshot(scene=scene, fname="icosahedron_test_2.png")

img = Image.open("icosahedron_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(icosahedron_actor_2)