Note
Go to the end to download the full example code
Spiky Sphere#
In this tutorial, we show how to create a sphere with spikes.
import itertools
import numpy as np
import fury
Create a sphere actor. Define the center, radius and color of a sphere. The sphere actor is made of points (vertices) evenly distributed on a sphere. Let’s create a scene.
scene = fury.window.Scene()
The vertices are connected with triangles in order to specify the direction
of the surface normal.
prim_sphere
provides a sphere with evenly distributed points
To be able to visualize the vertices, let’s define a point actor with green color.
point_actor = fury.actor.point(vertices, point_radius=0.01, colors=(0, 1, 0))
Normals are the vectors that are perpendicular to the surface at each vertex. We specify the normals at the vertices to tell the system whether triangles represent curved surfaces.
The normals are usually used to calculate how the light will bounce on the surface of an object. However, here we will use them to direct the spikes (represented with arrows). So, let’s create an arrow actor at the center of each vertex.
To be able to visualize the surface of the primitive sphere, we use
get_actor_from_primitive
.
primitive_colors = np.zeros(vertices.shape)
primitive_colors[:, 2] = 180
primitive_actor = fury.utils.get_actor_from_primitive(
vertices=vertices,
triangles=triangles,
colors=primitive_colors,
normals=normals,
backface_culling=True,
)
We add all actors (visual objects) defined above to the scene.
scene.add(point_actor)
scene.add(arrow_actor)
scene.add(primitive_actor)
scene.add(fury.actor.axes())
The ShowManager class is the interface between the scene, the window and the interactor.
showm = fury.window.ShowManager(
scene, size=(900, 768), reset_camera=False, order_transparent=True
)
/opt/homebrew/Caskroom/miniforge/base/envs/py39/lib/python3.9/site-packages/sphinx_gallery/gen_rst.py:722: UserWarning: We'll no longer accept the way you call the __init__ function in future versions of FURY.
Here's how to call the Function __init__: __init__(self_value, scene='value', title='value', size='value', png_magnify='value', reset_camera='value', order_transparent='value', interactor_style='value', stereo='value', multi_samples='value', max_peels='value', occlusion_ratio='value')
exec(self.code, self.fake_main.__dict__)
We want to make a small animation for fun!
We can determine the duration of animation with using the counter
.
Use itertools to avoid global variables.
The timer will call this user defined callback every 200 milliseconds. The application will exit after the callback has been called 20 times.
def timer_callback(_obj, _event):
cnt = next(counter)
showm.scene.azimuth(0.05 * cnt)
primitive_actor.GetProperty().SetOpacity(cnt / 10.0)
showm.render()
if cnt == 20:
showm.exit()
showm.add_timer_callback(True, 200, timer_callback)
showm.start()
fury.window.record(showm.scene, size=(900, 768), out_path="viz_spiky.png")
/opt/homebrew/Caskroom/miniforge/base/envs/py39/lib/python3.9/site-packages/sphinx_gallery/gen_rst.py:722: UserWarning: We'll no longer accept the way you call the record function in future versions of FURY.
Here's how to call the Function record: record(scene='value', cam_pos='value', cam_focal='value', cam_view='value', out_path='value', path_numbering='value', n_frames='value', az_ang='value', magnification='value', size='value', reset_camera='value', screen_clip='value', stereo='value', verbose='value')
exec(self.code, self.fake_main.__dict__)
Instead of arrows, you can choose other geometrical objects such as cones, cubes or spheres.
Total running time of the script: (0 minutes 4.335 seconds)