File: beam_shape.py

package info (click to toggle)
python-pyvista 0.44.1-11
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 159,804 kB
  • sloc: python: 72,164; sh: 118; makefile: 68
file content (152 lines) | stat: -rw-r--r-- 4,718 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""
.. _light_beam_shape_example:

Beam Shape
~~~~~~~~~~

The default directional lights are infinitely distant point sources, for which
the only geometric customization option is the choice of beam direction defined
by the light's position and focal point. Positional lights, however, have more
options for beam customization.

Consider two hemispheres:
"""

# sphinx_gallery_thumbnail_number = 5
from __future__ import annotations

import pyvista as pv

plotter = pv.Plotter()

hemi = pv.Sphere().clip()
hemi.translate((-1, 0, 0), inplace=True)
plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

hemi = hemi.rotate_z(180, inplace=False)
plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

plotter.show()


# %%
# We can see that the default lighting does a very good job of articulating the
# shape of the hemispheres.
#
# Let's shine a directional light on them, positioned between the hemispheres and
# oriented along their centers:

plotter = pv.Plotter(lighting='none')

hemi = pv.Sphere().clip()
hemi.translate((-1, 0, 0), inplace=True)
plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

hemi = hemi.rotate_z(180, inplace=False)
plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

light = pv.Light(position=(0, 0, 0), focal_point=(-1, 0, 0))
plotter.add_light(light)

plotter.show()


# %%
# Both hemispheres have their surface lit on the side that faces the light.
# This is consistent with the point source positioned at infinity, directed from
# the light's nominal position toward the focal point.
#
# Now let's change the light to a positional light (but not a spotlight):

plotter = pv.Plotter(lighting='none')

hemi = pv.Sphere().clip()
hemi.translate((-1, 0, 0), inplace=True)
plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

hemi = hemi.rotate_z(180, inplace=False)
plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

light = pv.Light(position=(0, 0, 0), focal_point=(-1, 0, 0))
light.positional = True
light.cone_angle = 90
plotter.add_light(light)

plotter.show()


# %%
# Now the inner surface of both hemispheres is lit. A positional light with a
# cone angle of 90 degrees (or more) acts as a point source located at the
# light's nominal position. It could still display attenuation, see the
# :ref:`attenuation_example` example.
#
# Switching to a spotlight (i.e. a positional light with a cone angle less
# than 90 degrees) will enable beam shaping using the :py:attr:`pyvista.Light.exponent`
# property. Let's put our hemispheres side by side for this, and put a light in
# the center of each: one spotlight, one merely positional.

plotter = pv.Plotter(lighting='none')

hemi = pv.Sphere().clip()
plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

offset = 1.5
hemi = hemi.translate((0, offset, 0), inplace=False)
plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

# non-spot positional light in the center of the first hemisphere
light = pv.Light(position=(0, 0, 0), focal_point=(-1, 0, 0))
light.positional = True
light.cone_angle = 90
# add attenuation to reduce cross-talk between the lights
light.attenuation_values = (0, 0, 2)
plotter.add_light(light)

# spotlight in the center of the second hemisphere
light = pv.Light(position=(0, offset, 0), focal_point=(-1, offset, 0))
light.positional = True
light.cone_angle = 89.9
# add attenuation to reduce cross-talk between the lights
light.attenuation_values = (0, 0, 2)
plotter.add_light(light)

plotter.show()


# %%
# Even though the two lights only differ by a fraction of a degree in cone angle,
# the beam shaping effect enabled for spotlights causes a marked difference in
# the result.
#
# Once we have a spotlight we can change its :py:attr:`pyvista.Light.exponent`
# to make the beam shape sharper or broader. Three spotlights with varying
# sharpness:

plotter = pv.Plotter(lighting='none')
hemi_template = pv.Sphere().clip()

centers = [(0, 0, 0), (0, 1.5, 0), (0, 1.5 * 0.5, 1.5 * 3**0.5 / 2)]
exponents = [1, 0.3, 5]

for center, exponent in zip(centers, exponents):
    hemi = hemi_template.copy()
    hemi.translate(center, inplace=True)
    plotter.add_mesh(hemi, color='cyan', smooth_shading=True)

    # spotlight in the center of the hemisphere, shining into it
    focal_point = center[0] - 1, center[1], center[2]
    light = pv.Light(position=center, focal_point=focal_point)
    light.positional = True
    light.cone_angle = 89.9
    light.exponent = exponent
    # add attenuation to reduce cross-talk between the lights
    light.attenuation_values = (0, 0, 2)
    plotter.add_light(light)

plotter.show()


# %%
# The spotlight with exponent 0.3 is practically uniform, and the one with
# exponent 5 is visibly focused along the axis of the light.