.. _axis_scaling_tut:
.. role:: raw-html(raw)
:format: html
****************************************
Scaling
****************************************
For 3D plotting, the visualization information is not only dependent on the domains of the displayed
objects, but the visual 'form' of the surfaces which are to be interpreted. The following sections
describe the various methods to be applied for displaying 3D objects.
Axis Scaling
=========================================================================================
When Mathplotlib renders a 2D plot, the minimum and maximum for the coordinate axes
are automatically set based on the data ranges being plotted. For 3D surfaces, lines,
etc., axis scaling cannot generally be relied on for the visualization.
As a result, scaling is directly set using these approaches.
* explicitly set the axis ranges.
* set by axes ranges based on the objects that are added to the 3D axes.
* scale all three axes uniformly based on the objects that are added to the 3D axes.
These three approaches are described below.
Explicit Axis Setting
-----------------------------------------------------------------------------------------
The coordinate axes scaling for a 3D plot can be set using
the *matplotlib.axes.Axes* (ax) methods::
ax.set_xlim(left,right)
ax.set_ylim(bottom,top)
ax.set_zlim(bottom,top)
These method have multiple parameters, for example, follow the
`set_xlim `_
method link.
Most of the examples provided in this S3Dlib documentation use a single
method call using named arguments as::
ax.set( xlim=(xmin,xmax), ylim=(ymin,ymax), zlim=(zmin,zmax) )
where a list or tuple of the minimum and maximum values are set for each axis.
.. _object_scale:
Object Axis Setting
-----------------------------------------------------------------------------------------
To exemplify axis scaling based on objects, four surface objects are created and
then translated from the origin using the script:
.. literalinclude:: source/tut_scaling.py
:language: python
:lines: 12-23
Scaling of the axes based on the objects added to the 3D axes, *ax*, is made using the method::
s3d.auto_scale(ax,*obj3d)
where the first parameter, *ax*, is the axis object to which 3D objects are added.
Multiple object arguments are designated by :raw-html:`*obj3d`.
The result of plotting the four example objects using the *auto_scale* method is:
.. image:: images/scaling_1.png
:class: sphx-glr-single-img
In this case, the ranges for each axis are independently set, based and the maximum
and minimum of all objects passed into the *auto_scale* method as::
s3d.auto_scale(ax,sphere,cube,cubeA,icosa)
where *ax* is the axes object.
.. _equal_axis_setting:
Equal Axis Setting
-----------------------------------------------------------------------------------------
When the set of objects must be viewed with similar scaling along all three coordinate
axes, additional named parameters in the the *auto_scale* method may be passed as::
s3d.auto_scale(ax,*obj3d, **kargs )
========== ========================== ============ ================================
key value when defined default control
========== ========================== ============ ================================
uscale float or int not defined scale for axis min max limits
rscale float or int not defined scale for axes centered limits
========== ========================== ============ ================================
If defined, *uscale* is a number in the range from 0.5 to 2.5 and is used to scale the range.
The default value is 1. Outside of the range, the maximum minimum values will
be used. If *uscale* is not a number, the default value is 1.
This provides a simple
method of viewing 3D shapes without distortions. So, using a value of True for the
four-object example plot:
.. image:: images/scaling_2.png
:class: sphx-glr-single-img
Now spheres, cubes, and icosahedrons appear as spheres, cubes, and icosahedrons without
distortion.
In a similar manner, *rscale* is a scaling factor for axes with min values being
the negative of the maximum value. Using *rscale* produces:
.. image:: images/scaling_3.png
:class: sphx-glr-single-img
If *uscale* and *rscale* are both defined, *uscale* will be ignored.
.. note::
The example plots were made with a figure aspect ratio of 1. However, for figures
aspects other than 1, the visualizations of these object will be dependent,
not only on the axes length ratios, but also the axes viewing elevation and
azimuth. Any changes to the elevation or azimuth will change the distortion
of the surfaces.
.. literalinclude:: source/tut_scaling.py
:language: python
Shading and Highlighting
=========================================================================================
'Correct' shading and highlighting **must** be viewed with similar scaling along all three
axes. When not the case, shading will be 'distorted' along with the geometry.
To compensate for this effect, the argument *ax* should be assigned to the 3Daxis for the
surface object *shade* and *hilite* methods. The following figure shows the effect of axes lengths.
The plot on the left shows the 'actual' shape of the object. The plot on the right,
'fits' the object in scaled axes with scaled shading.
.. image:: images/scaling_4.png
:class: sphx-glr-single-img
Considering the choices shown in the figure above, the 'appropriate' visualization of
geometry and shading is dependent on the intention of 3D visualization. Specifically,
are X, Y, and Z spatial dimensions or do they represent different dimensional values?
.. literalinclude:: source/tut_scaling_shade.py
:language: python
Object Range
=========================================================================================
The sizes of surface, line and vector objects are determined from the dictionary
property *bounds*. For example, this dictionary for a *surface* object is::
dict = surface.bounds
The *bounds* dictionary have values which are 2 element lists for the minimum and maximum values.
The keys are shown in the following table:
========== ==============================================
key value: [minimum, maximum]
========== ==============================================
xlim x range
ylim y range
zlim z range
rorg radial distance from the origin
r_xy radial distance from the z-axis (xy plane)
vlim scalar value used for colormapping
========== ==============================================
Surface Function Domain
=========================================================================================
All base surfaces are initialized in the x,y,z domain from -1 to 1. When plotting
3D functional surfaces, either:
* normalize the function of interest into the coordinate domains of -1 to 1, or
* change the domain of the base surface prior to functional mapping using the *domain* method.
For planar base surfaces, domains may be changed using the method::
surface.domain(xlim,ylim,zcoor)
where xlim and ylim are the (min,max) arrays for the x and y domains of the surface.
If a single value is used for either xlim or ylim, the domain is set for the
plus and minus values. The zcoor is a single z-coordinate value for the plane.
For polar base surfaces, domains may be changed using the method::
surface.domain(radius,zcoor)
where radius is the disk surface radius.
For cylindrical base surfaces, domains may be changed using the method::
surface.domain(radius,zlim)
where zlim is the (min,max) array for the z domain of the surface.
If a single value is used for zlim, the domain is set for the
plus and minus values.
For spherical base surfaces, domains may be changed using the method::
surface.domain(radius)
For cubic base surfaces, domains may be changed using the method::
surface.domain(xlim,ylim,zlim)
Take for example of the
`McCormick function `_
which is defined in the domain as:
.. image:: images/mccormick.png
:class: sphx-glr-single-img
The simple plot, adjusting the domain and using auto scaling is:
.. image:: images/domain.png
:class: sphx-glr-single-img
.. literalinclude:: source/tut_domain.py
:language: python
:emphasize-lines: 15,26