0

I'm struggling to plot a triangulated mesh in plotly that works in RGL. I prefer to plot this with plotly for the ability to scroll over data and have hover info. I'm open to sticking with RGL if anybody knows how to do this.

Reprex data and the libraries:

library(rgl)
library(plotly)
library(SurfaceReconstruction)
library(dplyr)

plot_issue_dat <- structure(c(-2.058, -3.02, 4.437, -3.02, 5.8, 4.985, -0.715, 
4.985, 5.8, -0.715, -2.058, 5.458, 5.061, 12.443, 4.943, 4.471, 
6.809, 6.809, -3.024, -3.024, -116.181, -115.799, -116.153, -115.799, 
-115.493, -107.238, -115.701, -107.238, -115.493, -115.701, -116.181, 
-107.907, -115.557, -105.538, -111.077, -114.791, -114.172, -114.172, 
-114.397, -114.397, 203.556, 203.187, 205.384, 203.187, 205.988, 
192.985, 202.444, 192.985, 205.988, 202.444, 203.556, 193.987, 
207.515, 198.121, 198.177, 210.117, 208.797, 208.797, 201.275, 
201.275), dim = c(20L, 3L), dimnames = list(NULL, c("surf_x", 
"surf_y", "surf_z")))

I have a point cloud and create a surface mesh using the Advancing Front Reconstruction algorithm, this return a mesh3d object:

plot_issue_mesh <- SurfaceReconstruction::AFSreconstruction(plot_issue_dat)

> class(plot_issue_mesh)
[1] "mesh3d"

I print out the full contents at the end of this post.

So we can plot it using RGL like this:

mfrow3d(1, 2, sharedMouse = TRUE)
wire3d(plot_issue_mesh) 
axes3d()  
next3d()
points3d(x=plot_issue_dat, 
       y=plot_issue_dat, 
       z=plot_issue_dat)
axes3d()  

Which yields these paired plots: enter image description here

But when I try to use the same vertex/connectivity data with plotly, it gives me nothing at all:

plot_ly_dat_vert <- plot_issue_mesh$vb |> t()
plot_ly_dat_face <- plot_issue_mesh$it |> t()

plot_ly()|>
  add_trace(
    type="mesh3d",
    x = plot_ly_dat_vert[,1],
    y = plot_ly_dat_vert[,2],
    z = plot_ly_dat_vert[,3],
    i = plot_ly_dat_face[,1],
    j = plot_ly_dat_face[,2],
    k = plot_ly_dat_face[,3]
  )

enter image description here

Plotly does still plot just the vertices:

plot_ly()|>
  add_trace(
    x = plot_ly_dat_vert[,1],
    y = plot_ly_dat_vert[,2],
    z = plot_ly_dat_vert[,3]
  )

enter image description here

Version and Package Details

## [1] "R version 4.2.2 Patched (2022-11-10 r83330) Innocent and Trusting"

## [1] "RStudio Version 2022.12.0.353 Elsbeth Geranium"

    package     loadedversion
dplyr   dplyr   1.0.10
ggplot2     ggplot2     3.4.0
knitr   knitr   1.41
plotly  plotly  4.10.1
rgl     rgl     0.110.2
SurfaceReconstruction   SurfaceReconstruction   0.1.0
> plot_issue_mesh$vb
         [,1]     [,2]     [,3]     [,4]     [,5]     [,6]     [,7]     [,8]     [,9]    [,10]    [,11]
[1,]   -0.715   -3.020   -3.024   -2.058    4.437    4.471   12.443    4.985    5.458    5.061    6.809
[2,] -115.701 -115.799 -114.397 -116.181 -116.153 -114.791 -105.538 -107.238 -107.907 -115.557 -114.172
[3,]  202.444  203.187  201.275  203.556  205.384  210.117  198.121  192.985  193.987  207.515  208.797
[4,]    1.000    1.000    1.000    1.000    1.000    1.000    1.000    1.000    1.000    1.000    1.000
        [,12]    [,13]
[1,]    5.800    4.943
[2,] -115.493 -111.077
[3,]  205.988  198.177
[4,]    1.000    1.000

> plot_issue_mesh$it
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18]
[1,]    1    4    2    6    8    8    6   12    7     7     9    12    11     1     8     3     6     4
[2,]    2    1    1    3    7    3    2   11    3     6     7     7     6     3     9     8     4     5
[3,]    3    5    4    2    9    7    4   10    6    11    13    11    10    13    13    13    10    10
     [,19] [,20] [,21] [,22]
[1,]    13    10     5     5
[2,]     7     5    13     1
[3,]    12    12    12    13

> plot_issue_mesh$normals
            [,1]       [,2]        [,3]        [,4]       [,5]       [,6]       [,7]       [,8]       [,9]
[1,]  0.04487982 -0.9289559 -0.89572966 -0.29054707  0.2498839 -0.1312339  0.7863605 -0.2423399  0.3724951
[2,] -0.83876795 -0.3494553  0.08686093 -0.95390713 -0.9588761 -0.1204796  0.5823910  0.3784624 -0.7133183
[3,] -0.54263622  0.1221557 -0.43603158  0.07512296 -0.1345901  0.9840032 -0.2060528 -0.8933295 -0.5936534
[4,]  1.00000000  1.0000000  1.00000000  1.00000000  1.0000000  1.0000000  1.0000000  1.0000000  1.0000000
          [,10]      [,11]      [,12]      [,13]
[1,]  0.2388872  0.7250958  0.6054552  0.3288626
[2,] -0.9349205 -0.1093559 -0.7894580 -0.7705457
[3,]  0.2624054  0.6799098 -0.1008973 -0.5459933
[4,]  1.0000000  1.0000000  1.0000000  1.0000000

> plot_issue_mesh$remvert
 [1] 0 0 0 0 0 1 1 1 1 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[53] 1 1 1 1 1 1 1 1 1 1 1 1 1 1

> plot_issue_mesh$remface
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
myfatson
  • 354
  • 2
  • 14

1 Answers1

1

Try this:

tmesh <- plot_issue_mesh
plot_ly(
  x = tmesh$vb[1,], y = tmesh$vb[2,], z = tmesh$vb[3,],
  i = tmesh$it[1,]-1, j = tmesh$it[2,]-1, k = tmesh$it[3,]-1,
  type = "mesh3d"
) %>% layout(scene = list(aspectmode = "data"))
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • This seems to work! Can you please elaborate on what's going on here with the tmesh$it[1,]-1 and layout(scene = list(aspectmode = "data")), I wasn't able to track this down in the R plotly docs. – myfatson Jan 14 '23 at 15:23
  • 1
    See `?rgl::mesh3d` for a short description of the format. I'd recommend using `rgl::asEuclidean2(tmesh$vb)` to convert from homogeneous coordinates to Euclidean; they might be the same in this example, but they aren't always. – user2554330 Jan 14 '23 at 20:17
  • Thanks u/user2554330 , I’ve implemented the asEuclidean. After reviewing the rgl::mesh3d docs I still don’t understand why tmesh$it[1,]-1 is needed for this to work with plotly nor am I certain it’s not distorting the connectivity matrix. – myfatson Jan 16 '23 at 03:30
  • 1
    @myfatson `-1` because the indexing starts at 0 in JavaScript. – Stéphane Laurent Jan 16 '23 at 07:53