0

The matplotlib tutorial provides a nice example of how to draw a spherical suface:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z,  rstride=4, cstride=4, color='b')

plt.show()

From what I understand, this creates a 2D grid for each x, y, and z variable corresonding to the product of the parameters u and v. The calculated x, y, and z variables are then the cartesian coordinates created from the spherical coordinates in u and v.

My question is the following: Why does the input to plot_surface have to be in 2D arrays?

I suspect it has something to do with calculating the normals of each of the surface faces, but I can't seem to figure it out. Is there some detailed documentation that describes this?

This question seems to ask something similar, but the single answer isn't particularly enlightening.

Community
  • 1
  • 1
juniper-
  • 6,262
  • 10
  • 37
  • 65

2 Answers2

0

The Equation of a surface is:

  f(x,y,z)=c

where the constants characterize the surfaces. In the case of a circle it is:

(x^2 + y^2 + z^2)^(1/2) = c

Where c is the radius. each value of gives one surface. In other words, f(x,y,z) can be written as z=g(x,y). Now if you have to span an area with two independent variables x & y, both will have to be 2D arrays. note that both x and y will be 2D arrays and so will z.

  • Fair enough, but what do the indeces 3 and 4 in x[3][4] refer to then? What is the significance of having it in a 2D array versus one large 1D array? – juniper- Oct 27 '14 at 13:05
  • In memory, of course its a 1 D array. You are required to supply 2D arrays because of compatibility with other software. For example the function surface in MATLAB ( which is the inspiration here has a similar syntax). In both matlab, matplotlib as well as IDL's surface, you must supply 2D arrays. About the 3 and 4 in x[3][4] It is not clear what you are asking. – Corrupted MyStack Oct 27 '14 at 23:01
  • While x[3][4] is the element at position x(3,4) with the given unique value of u & v. Note that you used matrix multiplication to generate 2D arrays. Another way is meshgrid – Corrupted MyStack Oct 27 '14 at 23:07
0

A: Because the interface specification orders that.

However strange does that look, the 2D-parametric grid,

describing the surface [ R = const, u = < 0, 2pi >, v = < 0, pi > ] from Spherical coordinate space is translated into a cartesian-space via a mapping,

stored in a set of [ MAT2Dx[,], MAT2Dy[,], MAT2Dz[,] ]

because that is the requirement the .plot_surface() method requires the surface-data to be received.

>>> print ax.plot_surface.__doc__

        Create a surface plot.

        By default it will be colored in shades of a solid color,
        but it also supports color mapping by supplying the *cmap*
        argument.

        ============= ================================================
        Argument      Description
        ============= ================================================
        *X*, *Y*, *Z* Data values as 2D arrays
        *rstride*     Array row stride (step size)
        *cstride*     Array column stride (step size)
        *color*       Color of the surface patches
        *cmap*        A colormap for the surface patches.
        *facecolors*  Face colors for the individual patches
        *norm*        An instance of Normalize to map values to colors
        *vmin*        Minimum value to map
        *vmax*        Maximum value to map
        *shade*       Whether to shade the facecolors
        ============= ================================================

        Other arguments are passed on to
        :class:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`

By design, a surface is a 2D-entity, here parametrised either by in [R,u,v] or [X,Y,Z] coordinate system, and due to the ease of [R,u,v] analytic description of a sphere surface, the meshing started in [u,v]-grid produced by a pair of .linspace() methods, whereas remained R=const=10.

Further:

>>> print np.outer.__doc__

    Compute the outer product of two vectors.

    Given two vectors, ``a = [a0, a1, ..., aM]`` and
    ``b = [b0, b1, ..., bN]``,
    the outer product [1]_ is::

      [[a0*b0  a0*b1 ... a0*bN ]
       [a1*b0    .
       [ ...          .
       [aM*b0            aM*bN ]]

has created x, y, z matrices in a shape of [100,100], as a trigonometry-laws-based mapping of [u,v] -> x(u,v), y(u,v), z(u,v)

finally, .plot_surface() method has consumed these in

 x,y,z = np.broadcast_matrices( x, y, z )

before starting to produce a list of 2D-surface-objects ( to be plot ), iterating over the scope of the original [u,v]-2Dgrid.

user3666197
  • 1
  • 6
  • 50
  • 92
  • Yeah, but why? What's the significance of having it in a 2D array? I'm not intentionally being obtuse, I'm just simply looking for a simple example of why it's useful to do it that way. – juniper- Oct 27 '14 at 14:55
  • Ok, open the matplotlib sources for **`.plot_surface()`** method to see, how these data-structures get processed. – user3666197 Oct 27 '14 at 14:59