SOCR ≫ DSPA ≫ DSPA2 Topics ≫

In this DSPA Appendix we will demonstrate the surface rendering of various mathematical representations of shape, form, and size.

Note: This Appendix is purposely divided into four separate sections to reduce the page loading time and improve the user experiences. It’s not recommended the readers view the complete version (DSPA_Appendix_03_Geometric_Parametric_Surface_Viz_Complete.html) as this page is extremely complex.

1 Introduction

It is important to realize that there are different types of manifolds and their shape can be represented as a number of alternative mathematical objects. There are parametric, PDE, triangulated, implicit (\(f(x,y,x)=0\)) explicit (\(r=r(u,v)\)), and other analytic strategies to represent the surface topology. In addition, some manifolds are orientable and some are non-orientable, some are closed with no boundaries and some are open with boundaries. The deep topological classification of manifolds provides further details on the mathematical analytics approaches to represent form, shape and size. Below. We will demonstrate examples of visualizing common geometric manifolds and some mathematical models representing the boundaries of specific manifolds.

For example, a parametric mesh-based representation of an open surface with boundaries requires individual definition of each component: \(x=x(u,v)\),\(y=y(u,v)\), \(z=z(u,v)\). In the saddle point surface example below, we use a single parameter \(0\leq u=\phi <2\pi\). However, all other 3D scene components need to be transformed using spherical coordinates, e.g., the orthogonal vertical planes need to be parameterized using \(0\leq u=\phi <2\pi \text { and } 0\leq v=\psi <\pi\).

library(plotly)

# Define Saddle-point Surface
x <- sin(seq(0, 2*pi, length.out = 200))
y <- cos(seq(0, 2*pi, length.out = 200))
z <- sin(seq(0, 2*pi, length.out = 200))*cos(seq(0, 2*pi, length.out = 200))
#plot_ly(x = ~x, y = ~y, z = ~z, type = 'mesh3d',
#             contour=list(show=TRUE, color="#000", width=15, lwd=10),
#             opacity=1.0, hoverinfo="none", legendshow=F)

# Define plane 1 (X=Y)
phi1 <- pi/4  # x=y in spherical coordinates
psi1 <- seq(from = 0, to = pi, by = ((pi - 0)/(200 - 1)))
r1 = seq(from = -1, to = 1, by = ((1 - (-1))/(200 - 1)))  # r = radius
scale1 <- 1.1

# if you want to display planes as rectangles/squares
# you need to transform the radial measure (r1)
#for (i in 1:length(psi1)) {
#  r1[i] = min(1/abs(cos(psi1[i])), 1/abs(sin(psi1[i])))
#}
# plot(x=r1*cos(psi1), y=r1*sin(psi1))

x1 = scale1 * cos(phi1) * (r1 %o% sin(psi1))     # x1 = r1 cos(phi1)sin(psi1)
y1 = scale1 * x1                                 # x1 = y1
z1 = scale1 * (r1 %o% cos(psi1)) 

# Define plane 2 (Orthogonal to Plane 1 and along the Z axis)
phi2 <- (3*pi)/4  #  in spherical coordinates
psi2 <- seq(from = 0, to = pi, by = ((pi - 0)/(200 - 1)))
r2 = seq(from = -1, to = 1, by = ((1 -(-1))/(200 - 1)))  # r = radius

x2 = scale1 * cos(phi2) * (r2 %o% sin(psi2))     # x2 = r2 cos(phi2)sin(psi2)
y2 = scale1 * sin(phi2) * (r2 %o% sin(psi2))     # y2 = r2 sin(phi2)sin(psi2)
z2 = scale1 * (r2 %o% cos(psi2)) 

p <- plot_ly(x=~x1, y=~y1, z=~z1,   # draw vertical plane 1
        colors = c("yellow", "white"),type="surface", 
        hoverinfo="none", opacity=0.7, 
        legendshow=FALSE, showscale = FALSE) %>%
  add_trace(x=~x2, y=~y2, z=~z2,    # draw vertical plane 2 (orthogonal to 1)
        colors = c("blue", "yellow"),type="surface", 
        hoverinfo="none", opacity=0.7, 
        legendshow=FALSE, showscale = FALSE) %>%
  # draw the saddle point surface
  add_trace(x = ~x, y = ~y, z = ~z, type = 'mesh3d',
       contour=list(show=TRUE, color="#000", width=15, lwd=10),
       opacity=1.0, hoverinfo="none", legendshow=F) %>%
  # trace the boundary of the saddle point surface
  add_trace(x=~x, y=~y, z=~z, type="scatter3d", mode="lines", 
              line = list(width = 10, color="red"), name="Surface Boundary",
              hoverinfo="none", legendshow=F) %>%
  # trace the main Z-axis
  add_trace(x=0, y=0, z=~(scale1*2*z), type="scatter3d", mode="lines", 
              line = list(width = 10, color="navy blue"), name="Z",
              hoverinfo="none", legendshow=F) %>%
  layout(title = "Saddle Point with Planes")
p

On the other hand, an orientable closed surface without boundary can be displayed by explicitly defining a triangulation of the surface, as illustrated below for a tetrahedron.

library(plotly)

p <- plot_ly(type = 'mesh3d',
             # Define all (4) zero-cells (points or vertices)
             # P_i(x,y,z), 0<=i<4
             x = c(0, 0, 2, 0),
             y = c(0, 0, 0, 2),
             z = c(0, 2, 0, 0),
             
             # Next define all triples (i,j,k) of vertices that form a 2-cell face. 
             # All Tetrahedra have 4 faces
             i = c(0, 0, 0, 1),
             j = c(1, 2, 3, 2),
             k = c(2, 3, 1, 3),
             
             # Define the appearance of the 4 faces (2-cells)
             intensity = c(0, 0.33, 0.66, 1),
             color = c(0, 0.33, 0.66, 1),
             colors = colorRamp(c("yellow", "light blue", "navy blue"))
); p

Next, we demonstrate how to render a more complex, naturally-triangulated surface; 12-face Icosahedron:

library(plotly)
# http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html

phi <- (1 + sqrt(5))/2

p <- plot_ly(type = 'mesh3d',
             # define 12 vertices
             x = c(-1, 1, -1, 1, 0, 0, 0, 0, phi, phi, -phi, -phi),
             y = c(phi, phi, -phi, -phi, -1, 1, -1, 1, 0, 0, 0, 0),
             z = c(0, 0, 0, 0, phi, phi, -phi, -phi, -1, 1, -1, 1),
 
             # Define all 20 2-cells (faces) 
             i = c(0,0,0,0,0,1,5,11,10,7,3,3,3,3,3,4,2,6,8,9),
             j = c(11,5,1,7,10,5,11,10,7,1,9,4,2,6,8,9,4,2,6,8),
             k = c(5,1,7,10,11,9,4,2,6,8,4,2,6,8,9,5,11,10,7,1),
             # 0 1 2 3 4 5 6 7 8 9 10 11 
             # A B C D E F G H I J  K  L
             
             # Define the appearance
             facecolor = toRGB(viridisLite::viridis(20)),
             showscale = TRUE, 
             opacity=0.5
) 
traceEdges <- list( 
  x = c(-1, -phi, -phi, -1), 
  y = c(phi, 0, 0, phi), 
  z = c(0, -1, 1, 0), 
  line = list(
    color = "rgb(10, 10, 10)",  #dark color for line traces
    width = 20 # width of line
  ), 
  mode = "lines", 
  opacity = 1,
  type = "scatter3d"
)

# emphasize one of the faces by stressing the three 1-cells (edges)
p <- add_trace(p, x=traceEdges$x, y=traceEdges$y, z=traceEdges$z, type="scatter3d", mode="lines", line = list(color=traceEdges$line$color, width=traceEdges$line$width), showscale=T); p

The core of this DSPA Appendix section is divided into the following sections.

2 Geometric Primitive Surfaces with and without Boundaries

This section covers:

  • Saddle Point Surface
  • Geometric Shapes: 3D Spherical Parameterization
  • Torus Surface

3 Non-Orientable Surfaces

This section demonstrates some examples of non-orientable 2-manifolds embedded in \(R^3\) and \(R^4\):

  • Möbius Band Triangulation
  • Klein Bottle

4 Brain Surfaces

This section shows examples of visualizing (precomputed/triangulated) brain cortical surface models:

  • Human Brain
  • Rodent Brain

5 Animation of 4D Surfaces

This section illustrates an innovative approach to render (high-dimensional) surfaces that are natively embedded in 4D using time-like animation along one of the dimensions to generate 3D embeddings of the manifolds.

6 Volume Rendering

This section shows examples of visualizing solids, such as 3D MRIs, using volume rendering.

7 References

SOCR Resource Visitor number Web Analytics SOCR Email