Face Edge Visualizations

../../_images/edges_compare1.png

This example demonstrates the various operations to visualize the edges of surfaces. An ‘inner’ surface is added to the axis, showing the effect of the various techniques allowing the view ‘behind’ the edges.

The face edges of a surface can either be viewed using the surface object with modified facecolors or by using the ColorLine3DCollection object obtained from the surface property surface.edges. Similar results can be obtained with both methods. The minor difference between the surface and line plots is that color is determined from coordinates of facecenters or the coordinates of the edgecenters, respectively. However differences can be further made using surface and line methods, depending on the class type.

  • both surface and line objects can use colormapping operations.

  • Advantages for surface objects are that:

    • the surface shading will be applied to the surface object edges. Line shading is only dependent on the orientation of the line.
    • using non-transparent facecolors will ‘hide’ the back surface. Clipping is required for the line object to hide the back lines.
    • surface objects can be added to other surface objects to form a composite surface object.
  • Advantages for line objects are that:

    • the lines may be faded relative to the view.
    • lines may be used to construct projected surfaces.
    • an object behind the lines is viewable. With edge clipping, the rear edges will not be visible on the object.
    • line objects can be added to other line objects to for a composite line object.

As seen in the figure, the two visualizations on the right are identical. The only difference being the upper object is a surface object whereas the lower object is a line object.

import numpy as np
from scipy import special as sp
from matplotlib import pyplot as plt
import s3dlib.surface as s3d

#.. face edges versus surface.edges

# 1. Define functions to examine ....................................
NviewDir = s3d.elev_azim_2vector(30,-60)
viewDir = -1*NviewDir

def sphHar(rtp) :
    r, theta, phi = rtp
    m, l = 2,3
    r = sp.sph_harm(m, l, theta, phi).real
    return r, theta, phi

RTP = lambda xyz : s3d.SphericalSurface.coor_convert(xyz)

# 2. Setup and map surfaces .........................................
rez = 2

base = s3d.SphericalSurface(rez)
base.map_cmap_from_op(   lambda rtp : sphHar(rtp)[0], cmap='seismic' )
base.shade()

# Transparent Faces..
surf = s3d.SphericalSurface(rez)
surf.map_cmap_from_op(   lambda rtp : sphHar(rtp)[0], cmap='seismic' )
surf.set_facecolor([1,1,1,0])

# White Faces..
surf_w = s3d.SphericalSurface(rez)
surf_w.map_cmap_from_op( lambda rtp : sphHar(rtp)[0], cmap='seismic' )
surf_w.set_facecolor([1,1,1,1])

# Shaded, then White Faces..
surf_s = s3d.SphericalSurface(rez)
surf_s.map_cmap_from_op( lambda rtp : sphHar(rtp)[0], cmap='seismic' )
surf_s.shade()
surf_s.set_facecolor([1,1,1,1])  # note: set must follow shade

# Clipped, Shaded, then Transparent Faces..
surf_t = s3d.SphericalSurface(rez)
surf_t.map_cmap_from_op(   lambda rtp : sphHar(rtp)[0], cmap='seismic' )
surf_t.clip_plane(0,direction=viewDir) # \
surf_t.shade()                         #  | necessary order of operation
surf_t.set_facecolor([1,1,1,0])        # /

# Lines from surface edges..
edge = surf.edges
edge.map_cmap_from_op(   lambda xyz : sphHar(RTP(xyz))[0], cmap='seismic' )

# Lines with 'back' lines clipped..
edge_c = surf_w.edges
edge_c.map_cmap_from_op( lambda xyz : sphHar(RTP(xyz))[0], cmap='seismic' )
edge_c.clip_plane(0, direction=viewDir )

# Faded Lines..
edge_f = surf_w.edges
edge_f.map_cmap_from_op( lambda xyz : sphHar(RTP(xyz))[0], cmap='seismic' )
edge_f.fade()

# Shaded surface edges & clipped..
edge_s = base.edges
edge_s.clip_plane(0, direction=viewDir )

# ..........................................................................

objects = [base,None,None,None,
           surf,surf_w,surf_s,surf_t,
           edge,edge_c,edge_f,edge_s]
titles =  ['Shaded Surface',"'Inner' Surface",None,None,
          'Transparent Faces','White Faces','Shaded w/ White Faces' ,
          'Clipped, Shaded\nw/ Transparent Faces' ,
          'surface.edges','Clipped','Faded','Shaded Surface Edges\n& Clipped']

info = str(base) +'\n'+ str(edge)

# 3. Construct figure, add surfaces, and plot .....................

fig = plt.figure(figsize=(8,6))
fig.text(0.975,0.975,info, ha='right', va='top')
fig.text(0.01,0.5,'Surface Objects',color='tab:red',
    va='center',fontsize='x-large',fontweight='bold',rotation=90)
fig.text(0.01,0.18,'Line Objects',color='tab:red',
    va='center',fontsize='x-large',fontweight='bold',rotation=90)
minmax = (-0.75,0.75)
for i,obj in enumerate(objects) :
    if i==2 or i==3 : continue
    gball = s3d.SphericalSurface(3,color='lightgreen').domain(.5)
    ax = fig.add_subplot(3,4,1+i, projection='3d')
    ax.set(xlim=minmax, ylim=minmax, zlim=minmax )
    ax.set_axis_off()
    ax.set_title(titles[i],fontsize='medium')
    if i==1 : 
        ax.add_collection(gball.shade())
    else :
        ax.add_collection3d(obj)
        ax.add_collection(gball.shade())
fig.tight_layout(pad=0)
plt.show()