Graham G Graham G - 3 months ago 20
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.

Correct rendering of surface, but with more grid points.

Answer

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
simDat <- read.csv("testDat.csv")
#
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
nodeDat_ML <- read.csv("testDatNodes.csv")
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().

Plots from R and Matlab generated triangulations

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.