Search code examples
rshinyrgl

R rgl library planes3d() function not displaying planes in rgl widget window


I have been trying to plot a simple set of planes, using the planes3d() function in my rgl window of my shiny app and nothing is getting the planes to show up.

library("shiny")
library("rgl")

# helper method for making edges
make_edge3d <- function(u, v) { return(sort(c(u,v))) }
rad2deg <- function(rad) {(rad * 180) / (pi)}
deg2rad <- function(deg) {(deg * pi) / (180)}

get_direction_vector <- function(theta, phi){
  #Helper function that converts theta and phi (in degrees) into a direction vector
  theta <- deg2rad(theta)
  phi <- deg2rad(phi)
  Z <- sin(phi) * cos(theta)
  X <- sin(phi) * sin(theta)
  Y <- cos(phi)
  
  return( c(X, Y, Z))
}



#This function will plot the inputted simplicial complex
plot_shape3d <- function(verts, edges, ...){
  vert_x <- verts[,1]
  vert_y <- verts[,2]
  vert_z <- verts[,3]
  
  #Draws the Points
  for (i in 1:length(vert_x)){
      points3d(vert_x[i], vert_y[i], vert_z[i])
  }
  #Constructs the edges
  for(e in edges){
      e_vert <- verts$vert_lab %in% e
      p1x = verts$vert_x[e_vert][1]
      p2x = verts$vert_x[e_vert][2]
      p1y = verts$vert_y[e_vert][1]
      p2y = verts$vert_y[e_vert][2]
      p1z = verts$vert_z[e_vert][1]
      p2z = verts$vert_z[e_vert][2]
      lines3d(c(p1x, p2x), c(p1y, p2y), c(p1z, p2z))
  }
}

#This graphs filtration planes orthogonal to viewpoint vector going through each point
plot_filtration_planes <- function(verts, edges, direction){
  
  for (i in range(1:nrow(verts))){
      vert = verts[i,]
      a = direction[1]
      b = direction[2]
      c = direction[3]
      d = -vert[1] * a - vert[2] * b - vert[3] * c
      planes3d(a,b,c,d)
  }
  
}


#Main function that plots out the persistence diagram of the 3d simplicial complex
plot3d <- function(phi=0, theta=0, graph3d){
  
      #List of vertex coordinates
      vert_x <- c(0, 1, 2, 3, 4)
      vert_y <- c(2, 0, 2, 0, 2)
      vert_z <- c(0, 0, 0, 0, 0)
      #Vertex Labels
      vert_lab <- c("v1", "v2", "v3", "v4", "v5")
      verts <- data.frame(vert_x, vert_y,vert_z, vert_lab, stringsAsFactors = F)
      
      #Makes the edges between vertices
      edges <- list(
          make_edge3d("v1", "v2"),
          make_edge3d("v2", "v3"),
          make_edge3d("v3", "v4"),
          make_edge3d("v4", "v5")
      )
      

  #offset <-  -vert_x[i] * direction[1] - vert_y[i] * direction[2] - vert_z[i] * direction[3]
  
  #Opens up the rgl plot
  open3d(useNULL = TRUE)
  axes3d()
  
  #Plots out the W shape
  plot_shape3d(verts, edges)
  
  #Retrieves a direction vector from the camera position to the origin
  direction <- get_direction_vector(theta, phi)
  
  #Plots filtration planes
  plot_filtration_planes(verts, edges, direction)
  
  highlevel(integer())
  rgl.viewpoint(theta, phi - 90, zoom=.4)
  rglwidget()
}


ui <- fluidPage(
  titlePanel("PD visualizer"),
  tabsetPanel(
  
      tabPanel("3D", fluid=TRUE,
               sidebarLayout(
                   sidebarPanel(
                       sliderInput(inputId="theta", label="Choose a number between 0 and  pi for theta",
                                   value = 0, min=0, max=360, step=1, round=-2),
                       sliderInput(inputId="phi", label="Choose a number between 0 and two pi for phi",
                                   value = 0, min=0, max=180, step=1, round=-2)
                   ),
                   mainPanel(fluidRow(column(1, offset=0, rglwidgetOutput("ThreePD",  width = 400, height = 150))))
                   
               )
               
               
               
      )
  )
  
  
)

server <- function(input, output){
  
  
  output$PD <- renderCachedPlot({
      createPlot(input$num, input$diagonals, input$filtlines, input$graphfile)
      
      
      
  },
  cacheKeyExpr = {paste(toString(input$num),"Diagonals: ", input$diagonals, "filtlines: ", input$filtlines, "file: ", input$graphfile$datapath)}
  )
  #output$plot1 <- renderPlot({plotPD3D(input$theta, input$phi, input$graphfile3d, input$diagonals3d)})
  output$ThreePD <- renderRglwidget({
      plot3d(input$phi, input$theta, input$graphfile3d)
  }
  )
}
shinyApp(ui = ui, server = server)

The issue is occuring with the plot_filtration_planes function. I am attempting to plot 5 planes, one for each vertex, with these planes being orthogonal to the current viewpoint, as defined by phi and theta. The code seems to be fine for calculating the plane equation, however the planes don't appear anywhere in the rgl device when I call them using planes3d(). Any advice would be much appreciated for this!


Solution

  • A plane is infinite.
    rgl calculates visualization cube limits according to the max limits from all non infinite objects in the scene.
    If the plane doesn't belong to the max limits cube, you won't see it.
    On the contrary, if the scene contains as an example a cube crossed by the plane, the plane appears:

    library(rgl)
    library(magrittr)
    axes3d()
    cube3d(color="black", alpha=0.1) %>% scale3d(4,4,4) %>% wire3d
    planes3d(1, 0, 0, 3, col='red',alpha=1)
    

    In this example the plane x + 3 = 0 corresponding to the above plane3d call is displayed. enter image description here