Graham G - 1 month ago 5x
R Question

# how to plot non-convex surface from set of n x 3 data

Is there a straight forward way to plot a non-convex surface in R?

I have used something like the following for convex surfaces and it works fine:

``````xyz <- cbind(y,x,z)
tbr <- t(surf.tri(xyz, delaunayn(xyz)))
rgl.triangles(xyz[tbr,1], xyz[tbr,2], xyz[tbr,3])
``````

However, for non-convex surfaces, concave areas become filled. I think this is a problem with the function
`delaunayn()`
as it uses the Qhull library which does not support constrained Delaunay triangulations or mesh generation of non-convex objects.

Any suggestions appreciated.

P.S.

I have data as an ascii file but it has 3 columns and is 225 lines long. What is the best way of providing this?

Data available at: http://pastebin.com/R2p4Cf7d

The top of the plot should be concave! This is an image created using
`persp3d()`
of how the surface should look. It has been calculated using more grid points on a regular grid in polar coordinates, rather than using irregular collocation points.

The following solution is not perfect, but works if you have a copy of Matlab.

``````library(rgl)
library(geometry)
# Read in data - also at: http://pastebin.com/R2p4Cf7d
#
x   <- simDat[,1];y<-simDat[,2];z<-simDat[,3]
xyz <- cbind(simDat[,1],simDat[,2],simDat[,3])
#
triNodes <- delaunayn(xyz)
tbr1     <- t(surf.tri(xyz, triNodes ))
# Plot data from R generated triangles
open3d()
rgl.triangles(xyz[tbr1,1], xyz[tbr1,2], xyz[tbr1,3])
#
# Import data generated by Matlab function delaunay()
#  - also at: http://pastebin.com/vQV2Zaii
triNodes2  <- cbind(nodeDat_ML[,1], nodeDat_ML[,2], nodeDat_ML[,3],1)
#
tbr2 <- t(surf.tri(xyz, triNodes2))
# Plot data from Matlab generated triangles
open3d()
rgl.triangles(xyz[tbr2,1], xyz[tbr2,2], xyz[tbr2,3])
``````

The code produces the following two surfaces. The left plot is based on triangulation generated by the R function delaunayn(), and the right plot is based on triangulation generated from the Matlab function delaunay().

The Matlab generated data is available at: http://pastebin.com/vQV2Zaii

and the associated Matblab code is:

``````fname = 'testDat.csv';
tt = table2array(readtable(fname)); % get data
x =  tt(:,1);y = tt(:,2);z = tt(:,3);
tri = delaunay(x,y); % the triangulation data
trisurf(tri,x(:,1),y(:,1),z(:,1)); % surface plot
``````

The result is not entirely perfect as the final plot (right) has a spurious triangle.

I hope the above will be useful to anyone with a similar problem.