.. _visualization_tut:
.. role:: raw-html(raw)
:format: html
****************************************
3D Rendering
****************************************
Perceiving 3D objects on a 2D plane requires various visual 'clues' in the flat 2D image.
Basic options are using lines on the surface object or lightness variations on the surface
object. Methods to create such visualizations prior to Matplotlib rendering are:
* distinct edge or line color relative to the face color.
* surface with color mapping in one direction, usually in the vertical z-direction
* surface color shading that is based on surface normals relative to a lighting source position.
The following figure illustrates these three techniques for planar, circumferential and spherical
geometries.
.. image:: images/s3dvis.png
:class: sphx-glr-single-img
Compared to edge color or color mapping, shading emphasizes the shape for geometries.
This is particularly seen in the last example above for the spherical coordinate shape.
In addition, *s3dlib* includes further enhancements to shading for visualizing surfaces and lines.
For surfaces, the *hilite* method can be applied to a shaded surface to provide a 'glossy' texture.
Highlighting can also enhance the visualization for surfaces with small curvatures.
The perception of depth can be applied to lines using the *fade* method. The following figure
illustrates these two methods.
.. image:: images/s3dvis_2.png
:class: sphx-glr-single-img
In this above example, the grey colored object is first shown without any applied 3D enhancements
prior to rendering. As a result, the three-dimensionality of object is not perceived.
The :ref:`shading` guide provides detail descriptions of these methods.
For visualizations where portions of the front and back surfaces are viewable, 'correct' surface shading
is dependent on the orientation of the view. The shade and hilite method have an *ax* argument that can be
assigned to the 3D axis, which accommodates this condition. In addition, use of the axes view with a binary colormap can
be used to provide different colors to the front and back surfaces, as shown in the :ref:`bin_surf` example.
.. image:: images/s3dvis_3.png
:class: sphx-glr-single-img
In the above figure, a comparison of shaded visualizations is made for such a surface view. In this case, the 'bottom' of the
surface turns upward toward the view direction. The left figure only uses the lighting direction to produce shading (for
this case, the default direction). The figure on the right uses the view orientation for shading the surface
along with the lighting direction.
The :ref:`shading_open` guide provides more detail for using the shade and hilite arguments.
Using shading also provides the additional ability of using color to represent
a scalar field or regions on the surface while still emphasizing the shape, as shown in
the simple example below:
.. image:: images/s3dvis_4.png
:class: sphx-glr-single-img
The approach to shading a surface in Matplotlib differs than that used by S3Dlib.
Matplotlib has a
`LightSource `_
object that may be used with the Axes3D
`plot_surface `_
method. The S3Dlib shading is a simple 'KISS' approach, sufficient for providing the 3D 'clues' in the visualization.
Differences between S3Dlib and Matplotlib for creating 3D shading 'clues' are:
========================== =========================== =======================================
. S3Dlib Matplotlib
========================== =========================== =======================================
3D visualization shade method of an object LightSource argument of plot_surface
direction specification Cartesian vectors elevation and azimuth angles
geometry construction *prior* to Axes3D render *during* Axes3D render
========================== =========================== =======================================
Using the Cartesian vectors for directions in *S3Dlib* provides a consistent specification for
object orientation, transformations, shading, geometric mapping and color mapping. S3Dlib has two methods, *rtv* and *elev_azim_2vector*,
to accommodate translating between these two direction descriptions when the axes *view_init* method is used.
Or, as discussed above, the axes argument is provided in the call to the shade and hilite methods.
The S3Dlib preference is also based on the intended application, that being a mathematical versus a 'scene' perspective.
The S3Dlib 'geometry construction' provides a general method of constructing complex 3D visualizations. Although
S3Dllib objects are shaded prior to rendering, the advantage of the S3Dlib approach is:
1. A single composite surface can be constructed from multiple objects, preserving the z-order in the single composite.
For example :ref:`chainlinks`, :ref:`nacl`, :ref:`pycube`.
2. Composite objects can be shaded while retaining individual colormapping of each component.
For example :ref:`sliced_earth`, :ref:`double_helix`.
3. Objects can be constructed first, then used to construct
other objects. Only the final result needs be rendered.
For example :ref:`rgb_normals`, :ref:`fun011_contours`, :ref:`mobius_lines`, :ref:`filled_octa_edges`.
4. Effects of multiple lighting sources may be applied using combinations of colormapping,
shading and highlighting.
For example :ref:`lower_light`, :ref:`orange_peel`, :ref:`inner_glow`.
5. Useful for animations, objects can be added and removed from the axes during and after rendering.
For example :ref:`anim_cat2heli`, :ref:`anim_earth_moon`. All :ref:`animations` were constructed using
this approach for individual frames.
Script code for the above four figures follow:
.. literalinclude:: source/tut_s3dvis.py
:language: python
:emphasize-lines: 71-73,100,101,127,135,136,144